- Added history reading and parsing
- Added evaulation of history data (still work in progress)
- Added custom actions (#1455), so that we can manually do "Wake Up and Tune" (new button in actions)
- Started decoding DailyTotals records (need TDD for bolus and basal).
This commit is contained in:
Andy Rozman 2018-11-05 16:49:59 +00:00
parent 5b9bd2adfc
commit b4ce95902b
49 changed files with 2952 additions and 1214 deletions

View file

@ -64,7 +64,7 @@ android {
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
// dev_version: 2.0i // dev_version: 2.0i
version "medtronic-0.4" version "medtronic-0.5.1-SNAPSHOT"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"' buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'

View file

@ -69,6 +69,7 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin; import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin; import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin; import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
@ -89,6 +90,7 @@ import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import info.nightscout.androidaps.receivers.NSAlarmReceiver; import info.nightscout.androidaps.receivers.NSAlarmReceiver;
import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.services.Intents;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
import io.fabric.sdk.android.Fabric; import io.fabric.sdk.android.Fabric;
public class MainApp extends Application { public class MainApp extends Application {
@ -268,7 +270,7 @@ public class MainApp extends Application {
private void setBTReceiver() { private void setBTReceiver() {
// SP.putDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, null); // SP.putDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, null);
// SP.remove(RileyLinkConst.Prefs.LastGoodDeviceFrequency); SP.remove(MedtronicConst.Statistics.LastPumpHistoryEntry); // FIXME remove
// RileyLink framework needs to know, when BT was reconnected, so that we can reconnect to RL device // RileyLink framework needs to know, when BT was reconnected, so that we can reconnect to RL device
btReceiver = new BroadcastReceiver() { btReceiver = new BroadcastReceiver() {

View file

@ -1,12 +1,11 @@
package info.nightscout.androidaps.db; package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Objects; import com.google.common.base.MoreObjects;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
@ -14,9 +13,9 @@ import info.nightscout.androidaps.logging.L;
* Created by mike on 20.09.2017. * Created by mike on 20.09.2017.
*/ */
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS) @DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS)
public class TDD { public class TDD {
private static Logger log = LoggerFactory.getLogger(L.DATABASE); private static Logger log = LoggerFactory.getLogger(L.DATABASE);
@DatabaseField(id = true) @DatabaseField(id = true)
@ -32,17 +31,30 @@ public class TDD {
public double total; public double total;
public double getTotal(){ public double getTotal() {
return (total > 0d) ? total:(bolus+basal); return (total > 0d) ? total : (bolus + basal);
} }
public TDD() { } public TDD() {
}
public TDD(long date, double bolus, double basal, double total){
public TDD(long date, double bolus, double basal, double total) {
this.date = date; this.date = date;
this.bolus = bolus; this.bolus = bolus;
this.basal = basal; this.basal = basal;
this.total = total; this.total = total;
} }
@Override
public String toString() {
return MoreObjects.toStringHelper(this) //
.add("date", date) //
.add("bolus", bolus) //
.add("basal", basal) //
.add("total", total) //
.toString();
}
} }

View file

@ -1,10 +1,14 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import java.util.List;
import org.json.JSONObject; import org.json.JSONObject;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
@ -12,49 +16,99 @@ import info.nightscout.androidaps.data.PumpEnactResult;
public interface PumpInterface { public interface PumpInterface {
boolean isInitialized(); // true if pump status has been read and is ready to accept commands boolean isInitialized(); // true if pump status has been read and is ready to accept commands
boolean isSuspended(); // true if suspended (not delivering insulin)
boolean isBusy(); // if true pump is not ready to accept commands right now
boolean isConnected(); // true if BT connection is established boolean isSuspended(); // true if suspended (not delivering insulin)
boolean isConnecting(); // true if BT connection is in progress
boolean isBusy(); // if true pump is not ready to accept commands right now
boolean isConnected(); // true if BT connection is established
boolean isConnecting(); // true if BT connection is in progress
boolean isHandshakeInProgress(); // true if BT is connected but initial handshake is still in progress boolean isHandshakeInProgress(); // true if BT is connected but initial handshake is still in progress
void finishHandshaking(); // set initial handshake completed void finishHandshaking(); // set initial handshake completed
void connect(String reason); void connect(String reason);
void disconnect(String reason); void disconnect(String reason);
void stopConnecting(); void stopConnecting();
void getPumpStatus(); void getPumpStatus();
// Upload to pump new basal profile // Upload to pump new basal profile
PumpEnactResult setNewBasalProfile(Profile profile); PumpEnactResult setNewBasalProfile(Profile profile);
boolean isThisProfileSet(Profile profile); boolean isThisProfileSet(Profile profile);
long lastDataTime(); long lastDataTime();
double getBaseBasalRate(); // base basal rate, not temp basal double getBaseBasalRate(); // base basal rate, not temp basal
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering(); void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew); PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
//when the cancel request is requested by the user (forced), the pump should always do a real cancel
// some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
// when the cancel request is requested by the user (forced), the pump should always do a real cancel
PumpEnactResult cancelTempBasal(boolean enforceNew); PumpEnactResult cancelTempBasal(boolean enforceNew);
PumpEnactResult cancelExtendedBolus(); PumpEnactResult cancelExtendedBolus();
// Status to be passed to NS // Status to be passed to NS
JSONObject getJSONStatus(Profile profile, String profileName); JSONObject getJSONStatus(Profile profile, String profileName);
String deviceID(); String deviceID();
// Pump capabilities // Pump capabilities
PumpDescription getPumpDescription(); PumpDescription getPumpDescription();
// Short info for SMS, Wear etc // Short info for SMS, Wear etc
String shortStatus(boolean veryShort); String shortStatus(boolean veryShort);
boolean isFakingTempsByExtendedBoluses(); boolean isFakingTempsByExtendedBoluses();
PumpEnactResult loadTDDs(); PumpEnactResult loadTDDs();
List<CustomAction> getCustomActions();
PumpEnactResult executeCustomAction(CustomActionType customActionType);
} }

View file

@ -1,22 +1,28 @@
package info.nightscout.androidaps.plugins.Actions; package info.nightscout.androidaps.plugins.Actions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.activities.HistoryBrowseActivity;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.HistoryBrowseActivity;
import info.nightscout.androidaps.activities.TDDStatsActivity; import info.nightscout.androidaps.activities.TDDStatsActivity;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
@ -25,12 +31,13 @@ import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog;
import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog; import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog;
import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog; import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog;
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
@ -45,10 +52,12 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
static ActionsPlugin actionsPlugin = new ActionsPlugin(); static ActionsPlugin actionsPlugin = new ActionsPlugin();
static public ActionsPlugin getPlugin() { static public ActionsPlugin getPlugin() {
return actionsPlugin; return actionsPlugin;
} }
View actionsFragmentView;
SingleClickButton profileSwitch; SingleClickButton profileSwitch;
SingleClickButton tempTarget; SingleClickButton tempTarget;
SingleClickButton extendedBolus; SingleClickButton extendedBolus;
@ -59,24 +68,24 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
SingleClickButton tddStats; SingleClickButton tddStats;
SingleClickButton history; SingleClickButton history;
public ActionsFragment() { public ActionsFragment() {
super(); super();
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle savedInstanceState) {
try { try {
View view = inflater.inflate(R.layout.actions_fragment, container, false); View view = inflater.inflate(R.layout.actions_fragment, container, false);
profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch); profileSwitch = (SingleClickButton)view.findViewById(R.id.actions_profileswitch);
tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget); tempTarget = (SingleClickButton)view.findViewById(R.id.actions_temptarget);
extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus); extendedBolus = (SingleClickButton)view.findViewById(R.id.actions_extendedbolus);
extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel); extendedBolusCancel = (SingleClickButton)view.findViewById(R.id.actions_extendedbolus_cancel);
tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal); tempBasal = (SingleClickButton)view.findViewById(R.id.actions_settempbasal);
tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal); tempBasalCancel = (SingleClickButton)view.findViewById(R.id.actions_canceltempbasal);
fill = (SingleClickButton) view.findViewById(R.id.actions_fill); fill = (SingleClickButton)view.findViewById(R.id.actions_fill);
tddStats = view.findViewById(R.id.actions_tddstats); tddStats = view.findViewById(R.id.actions_tddstats);
history = view.findViewById(R.id.actions_historybrowser); history = view.findViewById(R.id.actions_historybrowser);
@ -90,6 +99,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
history.setOnClickListener(this); history.setOnClickListener(this);
tddStats.setOnClickListener(this); tddStats.setOnClickListener(this);
actionsFragmentView = view;
updateGUI(); updateGUI();
return view; return view;
} catch (Exception e) { } catch (Exception e) {
@ -99,34 +110,41 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
return null; return null;
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventInitializationChanged ev) { public void onStatusEvent(final EventInitializationChanged ev) {
updateGUI(); updateGUI();
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventRefreshOverview ev) { public void onStatusEvent(final EventRefreshOverview ev) {
updateGUI(); updateGUI();
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventExtendedBolusChange ev) { public void onStatusEvent(final EventExtendedBolusChange ev) {
updateGUI(); updateGUI();
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventTempBasalChange ev) { public void onStatusEvent(final EventTempBasalChange ev) {
updateGUI(); updateGUI();
} }
@Override @Override
protected void updateGUI() { protected void updateGUI() {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() != null) { if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null
&& ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() != null) {
profileSwitch.setVisibility(View.VISIBLE); profileSwitch.setVisibility(View.VISIBLE);
} else { } else {
profileSwitch.setVisibility(View.GONE); profileSwitch.setVisibility(View.GONE);
@ -144,34 +162,37 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
final boolean basalprofileEnabled = MainApp.isEngineeringModeOrRelease() final boolean basalprofileEnabled = MainApp.isEngineeringModeOrRelease()
&& pump.getPumpDescription().isSetBasalProfileCapable; && pump.getPumpDescription().isSetBasalProfileCapable;
if (!basalprofileEnabled || !pump.isInitialized() || pump.isSuspended()) if (!basalprofileEnabled || !pump.isInitialized() || pump.isSuspended())
profileSwitch.setVisibility(View.GONE); profileSwitch.setVisibility(View.GONE);
else else
profileSwitch.setVisibility(View.VISIBLE); profileSwitch.setVisibility(View.VISIBLE);
if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) { if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized()
|| pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) {
extendedBolus.setVisibility(View.GONE); extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.GONE); extendedBolusCancel.setVisibility(View.GONE);
} else { } else {
ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()); ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(
System.currentTimeMillis());
if (activeExtendedBolus != null) { if (activeExtendedBolus != null) {
extendedBolus.setVisibility(View.GONE); extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.VISIBLE); extendedBolusCancel.setVisibility(View.VISIBLE);
extendedBolusCancel.setText(MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toString()); extendedBolusCancel.setText(MainApp.gs(R.string.cancel) + " "
+ activeExtendedBolus.toString());
} else { } else {
extendedBolus.setVisibility(View.VISIBLE); extendedBolus.setVisibility(View.VISIBLE);
extendedBolusCancel.setVisibility(View.GONE); extendedBolusCancel.setVisibility(View.GONE);
} }
} }
if (!pump.getPumpDescription().isTempBasalCapable || !pump.isInitialized() || pump.isSuspended()) { if (!pump.getPumpDescription().isTempBasalCapable || !pump.isInitialized() || pump.isSuspended()) {
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.GONE); tempBasalCancel.setVisibility(View.GONE);
} else { } else {
final TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); final TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(
System.currentTimeMillis());
if (activeTemp != null) { if (activeTemp != null) {
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.VISIBLE); tempBasalCancel.setVisibility(View.VISIBLE);
@ -192,12 +213,89 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
else else
tempTarget.setVisibility(View.VISIBLE); tempTarget.setVisibility(View.VISIBLE);
if (!ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().supportsTDDs) tddStats.setVisibility(View.GONE); if (!ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().supportsTDDs)
else tddStats.setVisibility(View.VISIBLE); tddStats.setVisibility(View.GONE);
else
tddStats.setVisibility(View.VISIBLE);
checkCustomActions();
} }
}); });
} }
private String activePumpName;
private Map<String, CustomAction> currentCustomActions = new HashMap<>();
private List<SingleClickButton> customButtons = new ArrayList<>();
View.OnClickListener customActionsListener = v -> {
SingleClickButton btn = (SingleClickButton)v;
CustomAction customAction = this.currentCustomActions.get(btn.getText().toString());
ConfigBuilderPlugin.getPlugin().getActivePump().executeCustomAction(customAction.getCustomActionType());
};
private void checkCustomActions() {
PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
removeCustomActions();
if (activePump == null) {
return;
}
// add new actions
List<CustomAction> customActions = activePump.getCustomActions();
if (customActions != null) {
LinearLayout ll = actionsFragmentView.findViewById(R.id.action_buttons_layout);
for (CustomAction customAction : customActions) {
SingleClickButton btn = new SingleClickButton(getContext(), null, android.R.attr.buttonStyle);
btn.setText(MainApp.gs(customAction.getName()));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 0.5f);
layoutParams.setMargins(20, 8, 20, 8); // 10,3,10,3
btn.setLayoutParams(layoutParams);
btn.setOnClickListener(customActionsListener);
Drawable top = getResources().getDrawable(R.drawable.icon_actions_profileswitch);
btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null);
ll.addView(btn);
this.currentCustomActions.put(MainApp.gs(customAction.getName()), customAction);
this.customButtons.add(btn);
}
}
}
private void removeCustomActions() {
if (currentCustomActions.size() == 0)
return;
LinearLayout ll = actionsFragmentView.findViewById(R.id.action_buttons_layout);
for (SingleClickButton customButton : customButtons) {
ll.removeView(customButton);
}
customButtons.clear();
currentCustomActions.clear();
}
@Override @Override
public void onClick(View view) { public void onClick(View view) {

View file

@ -0,0 +1,48 @@
package info.nightscout.androidaps.plugins.Actions.defs;
/**
* Created by andy on 9/20/18.
*/
public class CustomAction {
private int name;
private String iconName;
private CustomActionType customActionType;
public CustomAction(int nameResourceId, CustomActionType actionType) {
this.name = nameResourceId;
this.customActionType = actionType;
}
public int getName() {
return name;
}
public String getIconName() {
return iconName;
}
public void setIconName(String iconName) {
this.iconName = iconName;
}
public CustomActionType getCustomActionType() {
return customActionType;
}
public void setCustomActionType(CustomActionType customActionType) {
this.customActionType = customActionType;
}
}

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps.plugins.Actions.defs;
/**
* Created by andy on 9/20/18.
*/
public interface CustomActionType {
String getKey();
}

View file

@ -42,71 +42,32 @@ import info.nightscout.utils.DecimalFormatter;
// When using this class, make sure that your first step is to create mConnection (see MedtronicPumpPlugin) // When using this class, make sure that your first step is to create mConnection (see MedtronicPumpPlugin)
// FIXME remove PumpDriver instances, just keep methods that do something here
public abstract class PumpPluginAbstract extends PluginBase implements PumpInterface, ConstraintsInterface { public abstract class PumpPluginAbstract extends PluginBase implements PumpInterface, ConstraintsInterface {
private static final Logger LOG = LoggerFactory.getLogger(PumpPluginAbstract.class);
protected static final PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult().success(false) protected static final PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult().success(false)
.enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump_driver)); .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) 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)); .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 PumpDescription pumpDescription = new PumpDescription();
// protected PumpDriverInterface pumpDriver;
protected PumpStatus pumpStatus; protected PumpStatus pumpStatus;
protected String internalName;
protected ServiceConnection serviceConnection = null; protected ServiceConnection serviceConnection = null;
protected boolean serviceRunning = false; protected boolean serviceRunning = false;
protected boolean isInitialized = false; // protected boolean isInitialized = false;
protected PumpDriverState pumpState = PumpDriverState.NotInitialized; protected PumpDriverState pumpState = PumpDriverState.NotInitialized;
protected boolean displayConnectionMessages = false; protected boolean displayConnectionMessages = false;
// protected PumpPluginAbstract(PumpDriverInterface pumpDriverInterface, //
// String internalName, //
// String fragmentClassName, //
// int pluginName, //
// int pluginShortName, //
// PumpType pumpType) {
// this(pumpDriverInterface, //
// internalName, //
// new PluginDescription() //
// .mainType(PluginType.PUMP) //
// .fragmentClass(fragmentClassName) //
// .pluginName(pluginName) //
// .shortName(pluginShortName), //
// pumpType //
// );
// }
protected PumpPluginAbstract(PluginDescription pluginDescription, PumpType pumpType) { protected PumpPluginAbstract(PluginDescription pluginDescription, PumpType pumpType) {
super(pluginDescription); super(pluginDescription);
LOG.error("After super called.");
// this.pumpDriver = pumpDriverInterface;
this.internalName = internalName;
LOG.error("Before Init Pump Statis Data called.");
pumpDescription.setPumpDescription(pumpType); pumpDescription.setPumpDescription(pumpType);
initPumpStatusData(); initPumpStatusData();
LOG.error("Before set description");
LOG.error("Before pumpDriver");
// this.pumpDriver.initDriver(this.pumpStatus, this.pumpDescription);
// initPumpStatusData();
}
protected String getInternalName() {
return this.internalName;
} }
@ -165,7 +126,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public boolean isInitialized() { public boolean isInitialized() {
return pumpState != PumpDriverState.NotInitialized; return PumpDriverState.isInitialized(pumpState);
} }
@ -195,26 +156,26 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public void connect(String reason) { public void connect(String reason) {
if (displayConnectionMessages) if (displayConnectionMessages)
LOG.warn("connect (reason={}) [PumpPluginAbstract] - Not implemented.", reason); LOG.warn("connect (reason={}) [PumpPluginAbstract] - default (empty) implementation.", reason);
} }
public void disconnect(String reason) { public void disconnect(String reason) {
if (displayConnectionMessages) if (displayConnectionMessages)
LOG.warn("disconnect (reason={}) [PumpPluginAbstract] - Not implemented.", reason); LOG.warn("disconnect (reason={}) [PumpPluginAbstract] - default (empty) implementation.", reason);
} }
public void stopConnecting() { public void stopConnecting() {
if (displayConnectionMessages) if (displayConnectionMessages)
LOG.warn("stopConnecting [PumpPluginAbstract] - Not implemented."); LOG.warn("stopConnecting [PumpPluginAbstract] - default (empty) implementation.");
} }
@Override @Override
public boolean isHandshakeInProgress() { public boolean isHandshakeInProgress() {
if (displayConnectionMessages) if (displayConnectionMessages)
LOG.warn("isHandshakeInProgress [PumpPluginAbstract] - Not implemented."); LOG.warn("isHandshakeInProgress [PumpPluginAbstract] - default (empty) implementation.");
return false; return false;
} }
@ -222,7 +183,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
@Override @Override
public void finishHandshaking() { public void finishHandshaking() {
if (displayConnectionMessages) if (displayConnectionMessages)
LOG.warn("finishHandshaking [PumpPluginAbstract] - Not implemented."); LOG.warn("finishHandshaking [PumpPluginAbstract] - default (empty) implementation.");
} }

View file

@ -21,8 +21,8 @@ public enum PumpCapability {
ComboCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, TDD, ManualTDDLoad), // ComboCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, TDD, ManualTDDLoad), //
DanaCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, TDD, ManualTDDLoad), // DanaCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, TDD, ManualTDDLoad), //
DanaWithHistoryCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, StoreCarbInfo, TDD, ManualTDDLoad), // DanaWithHistoryCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, StoreCarbInfo, TDD, ManualTDDLoad), //
InsightCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill,TDD,BasalRate30min), // InsightCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, TDD), //
MedtronicCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, TDD), //
// BasalRates (separately grouped) // BasalRates (separately grouped)
BasalRate_Duration15minAllowed, // BasalRate_Duration15minAllowed, //
@ -34,19 +34,16 @@ public enum PumpCapability {
PumpCapability[] children; PumpCapability[] children;
PumpCapability() PumpCapability() {
{
} }
PumpCapability(PumpCapability...children) PumpCapability(PumpCapability... children) {
{
this.children = children; this.children = children;
} }
public boolean hasCapability(PumpCapability capability) public boolean hasCapability(PumpCapability capability) {
{
// we can only check presense of simple capabilities // we can only check presense of simple capabilities
if (capability.children != null) if (capability.children != null)
return false; return false;
@ -54,18 +51,15 @@ public enum PumpCapability {
if (this == capability) if (this == capability)
return true; return true;
if (this.children!=null) { if (this.children != null) {
for (PumpCapability child : children) { for (PumpCapability child : children) {
if (child == capability) if (child == capability)
return true; return true;
} }
return false; return false;
} } else
else
return false; return false;
} }
} }

View file

@ -8,12 +8,19 @@ public enum PumpDriverState {
NotInitialized, // NotInitialized, //
Connecting, // Connecting, //
Connected, //
Initialized, // Initialized, //
Ready,
Busy, // Busy, //
Suspended, // Suspended, //
; ;
public static boolean isConnected(PumpDriverState pumpState) { public static boolean isConnected(PumpDriverState pumpState) {
return pumpState == Connected || pumpState == Initialized || pumpState == Busy || pumpState == Suspended;
}
public static boolean isInitialized(PumpDriverState pumpState) {
return pumpState == Initialized || pumpState == Busy || pumpState == Suspended; return pumpState == Initialized || pumpState == Busy || pumpState == Suspended;
} }
} }

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.PumpCommon.defs; package info.nightscout.androidaps.plugins.PumpCommon.defs;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -8,8 +7,6 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.PumpCommon.data.DoseSettings; import info.nightscout.androidaps.plugins.PumpCommon.data.DoseSettings;
/** /**
* Created by andy on 02/05/2018. * Created by andy on 02/05/2018.
* *
@ -19,107 +16,102 @@ import info.nightscout.androidaps.plugins.PumpCommon.data.DoseSettings;
public enum PumpType { public enum PumpType {
GenericAAPS("Generic AAPS", 0.1d, null, // GenericAAPS("Generic AAPS", 0.1d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, // PumpTempBasalType.Percent, //
new DoseSettings(10,30, 24*60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // new DoseSettings(10, 30, 24 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities), // 0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities), //
// Cellnovo // Cellnovo
Cellnovo1("Cellnovo", 0.05d, null, // Cellnovo1("Cellnovo", 0.05d, null, //
new DoseSettings(0.05d, 30, 24*60, 1d, null), new DoseSettings(0.05d, 30, 24 * 60, 1d, null), //
PumpTempBasalType.Percent, PumpTempBasalType.Percent, //
new DoseSettings(5,30, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, // new DoseSettings(5, 30, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, //
0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), //
// Accu-Chek // Accu-Chek
AccuChekCombo("Accu-Chek Combo", 0.1d, null, // AccuChekCombo("Accu-Chek Combo", 0.1d, null, //
new DoseSettings(0.1d, 15, 12*60, 0.1d), // new DoseSettings(0.1d, 15, 12 * 60, 0.1d), //
PumpTempBasalType.Percent, PumpTempBasalType.Percent, new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
new DoseSettings(10, 15, 12*60,0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities), //
0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities), //
AccuChekSpirit("Accu-Chek Spirit", 0.1d, null, // AccuChekSpirit("Accu-Chek Spirit", 0.1d, null, //
new DoseSettings(0.1d, 15, 12*60, 0.1d), // new DoseSettings(0.1d, 15, 12 * 60, 0.1d), //
PumpTempBasalType.Percent, PumpTempBasalType.Percent, new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, //
new DoseSettings(10, 15, 12*60,0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities), //
0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities), //
AccuChekInsight("Accu-Chek Insight", 0.05d, DoseStepSize.InsightBolus, // AccuChekInsight("Accu-Chek Insight", 0.05d, DoseStepSize.InsightBolus, //
new DoseSettings(0.05d, 15, 24*60, 0.05d), // new DoseSettings(0.05d, 15, 24 * 60, 0.05d), //
PumpTempBasalType.Percent, PumpTempBasalType.Percent, new DoseSettings(10, 15, 12 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
new DoseSettings(10, 15, 12*60,0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.02d, 0.01d, null, PumpCapability.InsightCapabilities), //
0.02d, 0.01d, null, PumpCapability.InsightCapabilities), //
// Animas // Animas
AnimasVibe("Animas Vibe", 0.05d, null, // AnimasBolus? AnimasVibe("Animas Vibe", 0.05d, null, // AnimasBolus?
new DoseSettings(0.05d, 30, 12*60, 0.05d), // new DoseSettings(0.05d, 30, 12 * 60, 0.05d), //
PumpTempBasalType.Percent, // PumpTempBasalType.Percent, //
new DoseSettings(10, 30, 24*60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, // new DoseSettings(10, 30, 24 * 60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), // 0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), //
AnimasPing("Animas Ping", AnimasVibe), AnimasPing("Animas Ping", AnimasVibe),
// Dana // Dana
DanaR("DanaR", 0.05d, null, // DanaR("DanaR", 0.05d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, // PumpTempBasalType.Percent, //
new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, //
0.04d, 0.01d, null, PumpCapability.DanaCapabilities), 0.04d, 0.01d, null, PumpCapability.DanaCapabilities),
DanaRKorean("DanaR Korean", 0.05d, null, // DanaRKorean("DanaR Korean", 0.05d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, // PumpTempBasalType.Percent, //
new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, //
0.1d, 0.01d, null, PumpCapability.DanaCapabilities), 0.1d, 0.01d, null, PumpCapability.DanaCapabilities),
DanaRS("DanaRS", 0.05d, null, // DanaRS("DanaRS", 0.05d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Percent, // PumpTempBasalType.Percent, //
new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, // new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities), 0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities),
DanaRv2("DanaRv2", DanaRS), DanaRv2("DanaRv2", DanaRS),
// Insulet // Insulet
Insulet_Omnipod("Insulet Omnipod", 0.05d, null, // Insulet_Omnipod("Insulet Omnipod", 0.05d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, // PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 12*60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max
0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // basal rate 30u/hr
0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities),
// Medtronic // Medtronic
Medtronic_512_712("Medtronic 512/712", 0.05d, null, // Medtronic_512_712("Medtronic 512/712", 0.05d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, // PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, //
0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // TODO 0.05d, 0.05d, null, PumpCapability.MedtronicCapabilities),
Medtronic_515_715("Medtronic 515/715", Medtronic_512_712), Medtronic_515_715("Medtronic 515/715", Medtronic_512_712),
Medtronic_522_722("Medtronic 522/722", Medtronic_512_712), Medtronic_522_722("Medtronic 522/722", Medtronic_512_712),
Medtronic_523_723_Revel("Medtronic 523/723 (Revel)", 0.05d, null, // Medtronic_523_723_Revel("Medtronic 523/723 (Revel)", //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // 0.05d, null, new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, // PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.MedtronicCapabilities), //
Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", Medtronic_523_723_Revel), // TODO Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", Medtronic_523_723_Revel), //
Medtronic_640G("Medtronic 640G", 0.025d, null, // Medtronic_640G("Medtronic 640G", 0.025d, null, //
new DoseSettings(0.05d, 30, 8*60, 0.05d), // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), //
PumpTempBasalType.Absolute, // PumpTempBasalType.Absolute, //
new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), //
// Tandem // Tandem
TandemTSlim("Tandem t:slim", 0.01d, null, // TandemTSlim("Tandem t:slim", 0.01d, null, //
new DoseSettings(0.01d,15, 8*60, 0.4d), new DoseSettings(0.01d, 15, 8 * 60, 0.4d), PumpTempBasalType.Percent, new DoseSettings(1, 15, 8 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
PumpTempBasalType.Percent, 0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities),
new DoseSettings(1,15, 8*60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities),
TandemTFlex("Tandem t:flex", TandemTSlim), // TandemTFlex("Tandem t:flex", TandemTSlim), //
TandemTSlimG4("Tandem t:slim G4", TandemTSlim), // TandemTSlimG4("Tandem t:slim G4", TandemTSlim), //
@ -140,10 +132,9 @@ public enum PumpType {
private PumpCapability pumpCapability; private PumpCapability pumpCapability;
private PumpType parent; private PumpType parent;
private static Map<String,PumpType> mapByDescription; private static Map<String, PumpType> mapByDescription;
static static {
{
mapByDescription = new HashMap<>(); mapByDescription = new HashMap<>();
for (PumpType pumpType : values()) { for (PumpType pumpType : values()) {
@ -152,32 +143,38 @@ public enum PumpType {
} }
PumpType(String description, PumpType parent) PumpType(String description, PumpType parent) {
{
this.description = description; this.description = description;
this.parent = parent; this.parent = parent;
} }
PumpType(String description, PumpType parent, PumpCapability pumpCapability)
{ PumpType(String description, PumpType parent, PumpCapability pumpCapability) {
this.description = description; this.description = description;
this.parent = parent; this.parent = parent;
this.pumpCapability = pumpCapability; this.pumpCapability = pumpCapability;
} }
PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, //
DoseSettings extendedBolusSettings, // PumpType(String description, double bolusSize,
PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // DoseStepSize specialBolusSize, //
double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) DoseSettings extendedBolusSettings, //
{ PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings,
this(description, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability); PumpCapability specialBasalDurations, //
double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps,
PumpCapability pumpCapability) {
this(description, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings,
specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability);
} }
PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, //
DoseSettings extendedBolusSettings, // PumpType(String description, double bolusSize,
PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // DoseStepSize specialBolusSize, //
double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) DoseSettings extendedBolusSettings, //
{ PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings,
PumpCapability specialBasalDurations, //
double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep,
DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) {
this.description = description; this.description = description;
this.bolusSize = bolusSize; this.bolusSize = bolusSize;
this.specialBolusSize = specialBolusSize; this.specialBolusSize = specialBolusSize;
@ -206,6 +203,7 @@ public enum PumpType {
return this.pumpCapability; return this.pumpCapability;
} }
public double getBolusSize() { public double getBolusSize() {
return isParentSet() ? parent.bolusSize : bolusSize; return isParentSet() ? parent.bolusSize : bolusSize;
} }
@ -272,33 +270,33 @@ public enum PumpType {
public String getFullDescription(String i18nTemplate, boolean hasExtendedBasals) { public String getFullDescription(String i18nTemplate, boolean hasExtendedBasals) {
String unit = getPumpTempBasalType()==PumpTempBasalType.Percent ? "%" : ""; String unit = getPumpTempBasalType() == PumpTempBasalType.Percent ? "%" : "";
DoseSettings eb = getExtendedBolusSettings(); DoseSettings eb = getExtendedBolusSettings();
DoseSettings tbr = getTbrSettings(); DoseSettings tbr = getTbrSettings();
String extendedNote = hasExtendedBasals ? MainApp.gs(R.string.virtualpump_pump_def_extended_note) : ""; String extendedNote = hasExtendedBasals ? MainApp.gs(R.string.virtualpump_pump_def_extended_note) : "";
return String.format(i18nTemplate, // return String.format(
getStep("" + getBolusSize(), getSpecialBolusSize()), // i18nTemplate, //
eb.getStep(), eb.getDurationStep(), eb.getMaxDuration()/60, // getStep("" + getBolusSize(), getSpecialBolusSize()), //
getStep(getBaseBasalRange(), getBaseBasalSpecialSteps()), // eb.getStep(), eb.getDurationStep(),
tbr.getMinDose() + unit + "-" + tbr.getMaxDose() + unit, tbr.getStep() + unit, eb.getMaxDuration() / 60, //
tbr.getDurationStep(), tbr.getMaxDuration()/60, extendedNote); getStep(getBaseBasalRange(), getBaseBasalSpecialSteps()), //
tbr.getMinDose() + unit + "-" + tbr.getMaxDose() + unit, tbr.getStep() + unit, tbr.getDurationStep(),
tbr.getMaxDuration() / 60, extendedNote);
} }
private String getBaseBasalRange() private String getBaseBasalRange() {
{
Double maxValue = getBaseBasalMaxValue(); Double maxValue = getBaseBasalMaxValue();
return maxValue==null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue; return maxValue == null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue;
} }
private String getStep(String step, DoseStepSize stepSize) private String getStep(String step, DoseStepSize stepSize) {
{ if (stepSize != null)
if (stepSize!=null)
return step + " [" + stepSize.getDescription() + "] *"; return step + " [" + stepSize.getDescription() + "] *";
else else
return "" + step; return "" + step;
@ -306,23 +304,22 @@ public enum PumpType {
public boolean hasExtendedBasals() { public boolean hasExtendedBasals() {
return ((getBaseBasalSpecialSteps() !=null) || (getSpecialBolusSize() != null)); return ((getBaseBasalSpecialSteps() != null) || (getSpecialBolusSize() != null));
} }
public PumpCapability getSpecialBasalDurations() { public PumpCapability getSpecialBasalDurations() {
if (isParentSet()) if (isParentSet()) {
{
return parent.getSpecialBasalDurations(); return parent.getSpecialBasalDurations();
} } else {
else
{
return specialBasalDurations == null ? // return specialBasalDurations == null ? //
PumpCapability.BasalRate_Duration15and30minNotAllowed : specialBasalDurations; PumpCapability.BasalRate_Duration15and30minNotAllowed
: specialBasalDurations;
} }
} }
public double determineCorrectBolusSize(double bolusAmount) { public double determineCorrectBolusSize(double bolusAmount) {
if (bolusAmount == 0.0d) { if (bolusAmount == 0.0d) {
return bolusAmount; return bolusAmount;
@ -377,7 +374,7 @@ public enum PumpType {
} else { } else {
DoseStepSize specialBolusSize = getBaseBasalSpecialSteps(); DoseStepSize specialBolusSize = getBaseBasalSpecialSteps();
basalStepSize = specialBolusSize.getStepSizeForAmount((double) basalAmount); basalStepSize = specialBolusSize.getStepSizeForAmount((double)basalAmount);
} }
if (basalAmount > getTbrSettings().getMaxDose()) if (basalAmount > getTbrSettings().getMaxDose())

View file

@ -15,8 +15,6 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.Radio
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioResponse; 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.RLMessageType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor; 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.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
@ -35,6 +33,8 @@ public abstract class RileyLinkCommunicationManager {
private static final Logger LOG = LoggerFactory.getLogger(RileyLinkCommunicationManager.class); private static final Logger LOG = LoggerFactory.getLogger(RileyLinkCommunicationManager.class);
private static final int SCAN_TIMEOUT = 1500; private static final int SCAN_TIMEOUT = 1500;
private static final int ALLOWED_PUMP_UNREACHABLE = 10 * 60 * 1000; // 10 minutes
protected final RFSpy rfspy; protected final RFSpy rfspy;
protected final Context context; protected final Context context;
protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation
@ -51,10 +51,10 @@ public abstract class RileyLinkCommunicationManager {
private int timeoutCount = 0; private int timeoutCount = 0;
public RileyLinkCommunicationManager(Context context, RFSpy rfspy, RileyLinkTargetFrequency targetFrequency) { public RileyLinkCommunicationManager(Context context, RFSpy rfspy) {
this.context = context; this.context = context;
this.rfspy = rfspy; this.rfspy = rfspy;
this.targetFrequency = targetFrequency; this.targetFrequency = RileyLinkUtil.getRileyLinkTargetFrequency();
this.scanFrequencies = targetFrequency.getScanFrequencies(); this.scanFrequencies = targetFrequency.getScanFrequencies();
this.rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData(); this.rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData();
RileyLinkUtil.setRileyLinkCommunicationManager(this); RileyLinkUtil.setRileyLinkCommunicationManager(this);
@ -66,6 +66,15 @@ public abstract class RileyLinkCommunicationManager {
protected abstract void configurePumpSpecificSettings(); protected abstract void configurePumpSpecificSettings();
public void refreshRileyLinkTargetFrequency() {
if (this.targetFrequency != RileyLinkUtil.getRileyLinkTargetFrequency()) {
this.targetFrequency = RileyLinkUtil.getRileyLinkTargetFrequency();
this.scanFrequencies = targetFrequency.getScanFrequencies();
}
}
// All pump communications go through this function. // All pump communications go through this function.
protected <E extends RLMessage> E sendAndListen(RLMessage msg, int timeout_ms, Class<E> clazz) { protected <E extends RLMessage> E sendAndListen(RLMessage msg, int timeout_ms, Class<E> clazz) {
@ -87,11 +96,12 @@ public abstract class RileyLinkCommunicationManager {
if (rfSpyResponse.wasTimeout()) { if (rfSpyResponse.wasTimeout()) {
timeoutCount++; timeoutCount++;
if (timeoutCount >= 5) { long diff = System.currentTimeMillis() - pumpStatus.lastConnection;
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError,
RileyLinkError.NoContactWithDevice); if (diff > ALLOWED_PUMP_UNREACHABLE) {
timeoutCount = 0; LOG.warn("We reached max time that Pump can be unreachable. Starting Tuning.");
ServiceTaskExecutor.startTask(new WakeAndTuneTask()); ServiceTaskExecutor.startTask(new WakeAndTuneTask());
timeoutCount = 0;
} }
} }
} }
@ -117,6 +127,19 @@ public abstract class RileyLinkCommunicationManager {
} }
public boolean changeTargetFrequency(RileyLinkTargetFrequency targetFrequency) {
if (this.targetFrequency == targetFrequency) {
return false;
}
this.targetFrequency = targetFrequency;
this.scanFrequencies = targetFrequency.getScanFrequencies();
return true;
}
// FIXME change wakeup // FIXME change wakeup
// TODO we might need to fix this. Maybe make pump awake for shorter time (battery factor for pump) - Andy // TODO we might need to fix this. Maybe make pump awake for shorter time (battery factor for pump) - Andy
public void wakeUp(int duration_minutes, boolean force) { public void wakeUp(int duration_minutes, boolean force) {
@ -211,7 +234,7 @@ public abstract class RileyLinkCommunicationManager {
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData);
RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)0, RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)0,
(byte)0, (byte)0, 1000, (byte)0); (byte)0, (byte)0, 1500, (byte)0);
if (resp.wasTimeout()) { if (resp.wasTimeout()) {
LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]); LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]);
} else if (resp.looksLikeRadioPacket()) { } else if (resp.looksLikeRadioPacket()) {

View file

@ -184,7 +184,7 @@ public class RFSpy {
if (resp.looksLikeRadioPacket()) { if (resp.looksLikeRadioPacket()) {
// RadioResponse radioResp = resp.getRadioResponse(); // RadioResponse radioResp = resp.getRadioResponse();
// byte[] responsePayload = radioResp.getPayload(); // byte[] responsePayload = radioResp.getPayload();
LOG.info("writeToData: received radio response. Will decode at upper level"); LOG.trace("writeToData: received radio response. Will decode at upper level");
resetNotConnectedCount(); resetNotConnectedCount();
} }
// Log.i(TAG, "writeToData: raw response is " + ByteUtil.shortHexString(rawResponse)); // Log.i(TAG, "writeToData: raw response is " + ByteUtil.shortHexString(rawResponse));

View file

@ -17,7 +17,6 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkEncodingType; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkEncodingType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; 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.defs.RileyLinkTargetDevice;
@ -41,9 +40,10 @@ public abstract class RileyLinkService extends Service {
protected Context context; protected Context context;
protected RileyLinkBroadcastReceiver mBroadcastReceiver; protected RileyLinkBroadcastReceiver mBroadcastReceiver;
protected RileyLinkServiceData rileyLinkServiceData; protected RileyLinkServiceData rileyLinkServiceData;
protected RileyLinkTargetFrequency rileyLinkTargetFrequency;
// protected RileyLinkTargetFrequency rileyLinkTargetFrequency;
// protected static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock"; // protected static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock";
// protected static volatile PowerManager.WakeLock lockStatic = null; // protected static volatile PowerManager.WakeLock lockStatic = null;
// Our hardware/software connection // Our hardware/software connection
@ -57,7 +57,7 @@ public abstract class RileyLinkService extends Service {
RileyLinkUtil.setContext(this.context); RileyLinkUtil.setContext(this.context);
determineRileyLinkTargetFrequency(); determineRileyLinkTargetFrequency();
RileyLinkUtil.setRileyLinkService(this); RileyLinkUtil.setRileyLinkService(this);
RileyLinkUtil.setRileyLinkTargetFrequency(rileyLinkTargetFrequency); // RileyLinkUtil.setRileyLinkTargetFrequency(rileyLinkTargetFrequency);
RileyLinkUtil.setEncoding(getEncoding()); RileyLinkUtil.setEncoding(getEncoding());
initRileyLinkServiceData(); initRileyLinkServiceData();
} }

View file

@ -223,6 +223,11 @@ public class ByteUtil {
} }
public static int toInt(int b1, int b2, int b3) {
return toInt(b1, b2, b3, null, BitConversion.BIG_ENDIAN);
}
public static int toInt(int b1, int b2, BitConversion flag) { public static int toInt(int b1, int b2, BitConversion flag) {
return toInt(b1, b2, null, null, flag); return toInt(b1, b2, null, null, flag);
} }
@ -286,6 +291,14 @@ public class ByteUtil {
} }
public static String getHex(List<Byte> list) {
byte[] abyte0 = getByteArrayFromList(list);
return abyte0 != null ? getHex(abyte0, abyte0.length) : null;
}
public static String getHex(byte abyte0[], int i) { public static String getHex(byte abyte0[], int i) {
StringBuffer stringbuffer = new StringBuffer(); StringBuffer stringbuffer = new StringBuffer();
if (abyte0 != null) { if (abyte0 != null) {

View file

@ -35,7 +35,7 @@ public class DateTimeUtil {
int second = (int)atechDateTime; int second = (int)atechDateTime;
return new LocalDateTime(year, month, dayOfMonth, minute, second); return new LocalDateTime(year, month, dayOfMonth, hourOfDay, minute, second);
} }
@ -52,4 +52,56 @@ public class DateTimeUtil {
return atechDateTime; return atechDateTime;
} }
public static boolean isSameDay(LocalDateTime ldt1, LocalDateTime ldt2) {
return (ldt1.getYear() == ldt2.getYear() && //
ldt1.getMonthOfYear() == ldt2.getMonthOfYear() && //
ldt1.getDayOfMonth() == ldt2.getDayOfMonth());
}
public static long toATechDate(int year, int month, int dayOfMonth, int hour, int minutes, int seconds) {
long atechDateTime = 0L;
atechDateTime += year * 10000000000L;
atechDateTime += month * 100000000L;
atechDateTime += dayOfMonth * 1000000L;
atechDateTime += hour * 10000L;
atechDateTime += minutes * 100L;
atechDateTime += seconds;
return atechDateTime;
}
public static String toString(long atechDateTime) {
int year = (int)(atechDateTime / 10000000000L);
atechDateTime -= year * 10000000000L;
int month = (int)(atechDateTime / 100000000L);
atechDateTime -= month * 100000000L;
int dayOfMonth = (int)(atechDateTime / 1000000L);
atechDateTime -= dayOfMonth * 1000000L;
int hourOfDay = (int)(atechDateTime / 10000L);
atechDateTime -= hourOfDay * 10000L;
int minute = (int)(atechDateTime / 100L);
atechDateTime -= minute * 100L;
int second = (int)atechDateTime;
return getZeroPrefixed(dayOfMonth) + "." + getZeroPrefixed(month) + "." + year + " " + //
getZeroPrefixed(hourOfDay) + ":" + getZeroPrefixed(minute) + ":" + getZeroPrefixed(second);
}
private static String getZeroPrefixed(int number) {
return (number < 10) ? "0" + number : "" + number;
}
} }

View file

@ -95,4 +95,9 @@ public class StringUtil {
return val.toString(); return val.toString();
} }
public static void splitString(String s, int characters) {
}
} }

View file

@ -1,13 +1,14 @@
package info.nightscout.androidaps.plugins.PumpDanaR; package info.nightscout.androidaps.plugins.PumpDanaR;
import android.support.annotation.Nullable; import java.util.Date;
import java.util.List;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date; import android.support.annotation.Nullable;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -27,6 +28,8 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
@ -44,6 +47,7 @@ import info.nightscout.utils.SP;
*/ */
public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
protected Logger log = LoggerFactory.getLogger(L.PUMP); protected Logger log = LoggerFactory.getLogger(L.PUMP);
protected AbstractDanaRExecutionService sExecutionService; protected AbstractDanaRExecutionService sExecutionService;
@ -52,17 +56,14 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
public PumpDescription pumpDescription = new PumpDescription(); public PumpDescription pumpDescription = new PumpDescription();
protected AbstractDanaRPlugin() { protected AbstractDanaRPlugin() {
super(new PluginDescription() super(new PluginDescription().mainType(PluginType.PUMP).fragmentClass(DanaRFragment.class.getName())
.mainType(PluginType.PUMP) .pluginName(R.string.danarspump).shortName(R.string.danarpump_shortname).preferencesId(R.xml.pref_danars)
.fragmentClass(DanaRFragment.class.getName()) .description(R.string.description_pump_dana_r));
.pluginName(R.string.danarspump)
.shortName(R.string.danarpump_shortname)
.preferencesId(R.xml.pref_danars)
.description(R.string.description_pump_dana_r)
);
} }
@Override @Override
public void onStateChange(PluginType type, State oldState, State newState) { public void onStateChange(PluginType type, State oldState, State newState) {
// if pump profile was enabled need to switch to another too // if pump profile was enabled need to switch to another too
@ -73,17 +74,21 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
} }
} }
@Override @Override
public boolean isSuspended() { public boolean isSuspended() {
return DanaRPump.getInstance().pumpSuspended; return DanaRPump.getInstance().pumpSuspended;
} }
@Override @Override
public boolean isBusy() { public boolean isBusy() {
if (sExecutionService == null) return false; if (sExecutionService == null)
return false;
return sExecutionService.isConnected() || sExecutionService.isConnecting(); return sExecutionService.isConnected() || sExecutionService.isConnecting();
} }
// Pump interface // Pump interface
@Override @Override
public PumpEnactResult setNewBasalProfile(Profile profile) { public PumpEnactResult setNewBasalProfile(Profile profile) {
@ -96,7 +101,8 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
} }
if (!isInitialized()) { if (!isInitialized()) {
log.error("setNewBasalProfile not initialized"); log.error("setNewBasalProfile not initialized");
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED,
MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet); result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet);
return result; return result;
@ -104,14 +110,16 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
} }
if (!sExecutionService.updateBasalsInPump(profile)) { if (!sExecutionService.updateBasalsInPump(profile)) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE,
MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.failedupdatebasalprofile); result.comment = MainApp.gs(R.string.failedupdatebasalprofile);
return result; return result;
} else { } else {
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); Notification notification = new Notification(Notification.PROFILE_SET_OK,
MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.success = true; result.success = true;
result.enacted = true; result.enacted = true;
@ -120,6 +128,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
} }
} }
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
if (!isInitialized()) if (!isInitialized())
@ -132,7 +141,8 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
for (int h = 0; h < basalValues; h++) { for (int h = 0; h < basalValues; h++) {
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h]; Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
Double profileValue = profile.getBasalTimeFromMidnight(h * basalIncrement); Double profileValue = profile.getBasalTimeFromMidnight(h * basalIncrement);
if (profileValue == null) return true; if (profileValue == null)
return true;
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) { if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue); log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
@ -142,16 +152,19 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return true; return true;
} }
@Override @Override
public long lastDataTime() { public long lastDataTime() {
return DanaRPump.getInstance().lastConnection; return DanaRPump.getInstance().lastConnection;
} }
@Override @Override
public double getBaseBasalRate() { public double getBaseBasalRate() {
return DanaRPump.getInstance().currentBasal; return DanaRPump.getInstance().currentBasal;
} }
@Override @Override
public void stopBolusDelivering() { public void stopBolusDelivering() {
if (sExecutionService == null) { if (sExecutionService == null) {
@ -161,11 +174,14 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
sExecutionService.bolusStop(); sExecutionService.bolusStop();
} }
@Override @Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile)
.value();
if (percent < 0) { if (percent < 0) {
result.isTempCancel = false; result.isTempCancel = false;
result.enacted = false; result.enacted = false;
@ -211,6 +227,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return result; return result;
} }
@Override @Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
@ -230,11 +247,13 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
result.isPercent = false; result.isPercent = false;
result.isTempCancel = false; result.isTempCancel = false;
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount
+ " Asked: " + insulin);
return result; return result;
} }
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { if (connectionOK && pump.isExtendedInProgress
&& Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = true; result.enacted = true;
result.success = true; result.success = true;
result.comment = MainApp.gs(R.string.virtualpump_resultok); result.comment = MainApp.gs(R.string.virtualpump_resultok);
@ -255,6 +274,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return result; return result;
} }
@Override @Override
public PumpEnactResult cancelExtendedBolus() { public PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -278,6 +298,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
} }
} }
@Override @Override
public void connect(String from) { public void connect(String from) {
if (sExecutionService != null) { if (sExecutionService != null) {
@ -287,26 +308,33 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
} }
} }
@Override @Override
public boolean isConnected() { public boolean isConnected() {
return sExecutionService != null && sExecutionService.isConnected(); return sExecutionService != null && sExecutionService.isConnected();
} }
@Override @Override
public boolean isConnecting() { public boolean isConnecting() {
return sExecutionService != null && sExecutionService.isConnecting(); return sExecutionService != null && sExecutionService.isConnecting();
} }
@Override @Override
public void disconnect(String from) { public void disconnect(String from) {
if (sExecutionService != null) sExecutionService.disconnect(from); if (sExecutionService != null)
sExecutionService.disconnect(from);
} }
@Override @Override
public void stopConnecting() { public void stopConnecting() {
if (sExecutionService != null) sExecutionService.stopConnecting(); if (sExecutionService != null)
sExecutionService.stopConnecting();
} }
@Override @Override
public void getPumpStatus() { public void getPumpStatus() {
if (sExecutionService != null) { if (sExecutionService != null) {
@ -316,6 +344,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
} }
} }
@Override @Override
public JSONObject getJSONStatus(Profile profile, String profilename) { public JSONObject getJSONStatus(Profile profile, String profilename) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
@ -358,7 +387,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
pumpjson.put("battery", battery); pumpjson.put("battery", battery);
pumpjson.put("status", status); pumpjson.put("status", status);
pumpjson.put("extended", extended); pumpjson.put("extended", extended);
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); pumpjson.put("reservoir", (int)pump.reservoirRemainingUnits);
pumpjson.put("clock", DateUtil.toISOString(new Date())); pumpjson.put("clock", DateUtil.toISOString(new Date()));
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
@ -366,16 +395,19 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return pumpjson; return pumpjson;
} }
@Override @Override
public String deviceID() { public String deviceID() {
return DanaRPump.getInstance().serialNumber; return DanaRPump.getInstance().serialNumber;
} }
@Override @Override
public PumpDescription getPumpDescription() { public PumpDescription getPumpDescription() {
return pumpDescription; return pumpDescription;
} }
/** /**
* DanaR interface * DanaR interface
*/ */
@ -385,35 +417,51 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return sExecutionService.loadHistory(type); return sExecutionService.loadHistory(type);
} }
/** /**
* Constraint interface * Constraint interface
*/ */
@Override @Override
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) { public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
absoluteRate.setIfSmaller(DanaRPump.getInstance().maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), DanaRPump.getInstance().maxBasal, MainApp.gs(R.string.pumplimit)), this); absoluteRate.setIfSmaller(
DanaRPump.getInstance().maxBasal,
String.format(MainApp.gs(R.string.limitingbasalratio), DanaRPump.getInstance().maxBasal,
MainApp.gs(R.string.pumplimit)), this);
return absoluteRate; return absoluteRate;
} }
@Override @Override
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) { public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); percentRate.setIfGreater(0,
percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)),
this);
percentRate.setIfSmaller(
getPumpDescription().maxTempPercent,
String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent,
MainApp.gs(R.string.pumplimit)), this);
return percentRate; return percentRate;
} }
@Override @Override
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) { public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
insulin.setIfSmaller(DanaRPump.getInstance().maxBolus, String.format(MainApp.gs(R.string.limitingbolus), DanaRPump.getInstance().maxBolus, MainApp.gs(R.string.pumplimit)), this); insulin.setIfSmaller(
DanaRPump.getInstance().maxBolus,
String.format(MainApp.gs(R.string.limitingbolus), DanaRPump.getInstance().maxBolus,
MainApp.gs(R.string.pumplimit)), this);
return insulin; return insulin;
} }
@Override @Override
public Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) { public Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) {
return applyBolusConstraints(insulin); return applyBolusConstraints(insulin);
} }
@Nullable @Nullable
@Override @Override
public ProfileStore getProfile() { public ProfileStore getProfile() {
@ -422,49 +470,69 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return DanaRPump.getInstance().createConvertedProfile(); return DanaRPump.getInstance().createConvertedProfile();
} }
@Override @Override
public String getUnits() { public String getUnits() {
return DanaRPump.getInstance().getUnits(); return DanaRPump.getInstance().getUnits();
} }
@Override @Override
public String getProfileName() { public String getProfileName() {
return DanaRPump.getInstance().createConvertedProfileName(); return DanaRPump.getInstance().createConvertedProfileName();
} }
@Override @Override
public PumpEnactResult loadTDDs() { public PumpEnactResult loadTDDs() {
return loadHistory(RecordTypes.RECORD_TYPE_DAILY); return loadHistory(RecordTypes.RECORD_TYPE_DAILY);
} }
// Reply for sms communicator // Reply for sms communicator
public String shortStatus(boolean veryShort) { public String shortStatus(boolean veryShort) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
String ret = ""; String ret = "";
if (pump.lastConnection != 0) { if (pump.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection; Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
int agoMin = (int) (agoMsec / 60d / 1000d); int agoMin = (int)(agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " minago\n"; ret += "LastConn: " + agoMin + " minago\n";
} }
if (pump.lastBolusTime != 0) { if (pump.lastBolusTime != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @"
+ android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
} }
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()); TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin()
.getRealTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) { if (activeTemp != null) {
ret += "Temp: " + activeTemp.toStringFull() + "\n"; ret += "Temp: " + activeTemp.toStringFull() + "\n";
} }
ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()); ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(
System.currentTimeMillis());
if (activeExtendedBolus != null) { if (activeExtendedBolus != null) {
ret += "Extended: " + activeExtendedBolus.toString() + "\n"; ret += "Extended: " + activeExtendedBolus.toString() + "\n";
} }
if (!veryShort) { if (!veryShort) {
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits
+ " U\n";
} }
ret += "IOB: " + pump.iob + "U\n"; ret += "IOB: " + pump.iob + "U\n";
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
ret += "Batt: " + pump.batteryRemaining + "\n"; ret += "Batt: " + pump.batteryRemaining + "\n";
return ret; return ret;
} }
// TODO: daily total constraint // TODO: daily total constraint
@Override
public List<CustomAction> getCustomActions() {
return null;
}
@Override
public PumpEnactResult executeCustomAction(CustomActionType customActionType) {
return null;
}
} }

View file

@ -1,5 +1,12 @@
package info.nightscout.androidaps.plugins.PumpDanaRS; package info.nightscout.androidaps.plugins.PumpDanaRS;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -11,11 +18,6 @@ import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
@ -36,6 +38,8 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
@ -63,9 +67,11 @@ import info.nightscout.utils.T;
*/ */
public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
private Logger log = LoggerFactory.getLogger(L.PUMP); private Logger log = LoggerFactory.getLogger(L.PUMP);
private static DanaRSPlugin plugin = null; private static DanaRSPlugin plugin = null;
public static DanaRSPlugin getPlugin() { public static DanaRSPlugin getPlugin() {
if (plugin == null) if (plugin == null)
plugin = new DanaRSPlugin(); plugin = new DanaRSPlugin();
@ -79,19 +85,16 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
public static PumpDescription pumpDescription = new PumpDescription(); public static PumpDescription pumpDescription = new PumpDescription();
private DanaRSPlugin() { private DanaRSPlugin() {
super(new PluginDescription() super(new PluginDescription().mainType(PluginType.PUMP).fragmentClass(DanaRFragment.class.getName())
.mainType(PluginType.PUMP) .pluginName(R.string.danarspump).shortName(R.string.danarspump_shortname).preferencesId(R.xml.pref_danars)
.fragmentClass(DanaRFragment.class.getName()) .description(R.string.description_pump_dana_rs));
.pluginName(R.string.danarspump)
.shortName(R.string.danarspump_shortname)
.preferencesId(R.xml.pref_danars)
.description(R.string.description_pump_dana_rs)
);
pumpDescription.setPumpDescription(PumpType.DanaRS); pumpDescription.setPumpDescription(PumpType.DanaRS);
} }
@Override @Override
public void onStateChange(PluginType type, State oldState, State newState) { public void onStateChange(PluginType type, State oldState, State newState) {
// if pump profile was enabled need to switch to another too // if pump profile was enabled need to switch to another too
@ -102,6 +105,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
@Override @Override
protected void onStart() { protected void onStart() {
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
@ -113,6 +117,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
super.onStart(); super.onStart();
} }
@Override @Override
protected void onStop() { protected void onStop() {
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
@ -121,25 +126,25 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
MainApp.bus().unregister(this); MainApp.bus().unregister(this);
} }
@Override @Override
public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher,
FragmentActivity context) {
boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
if (allowHardwarePump || context == null) { if (allowHardwarePump || context == null) {
pluginSwitcher.invoke(); pluginSwitcher.invoke();
} else { } else {
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.allow_hardware_pump_text) builder.setMessage(R.string.allow_hardware_pump_text).setPositiveButton(R.string.yes, (dialog, id) -> {
.setPositiveButton(R.string.yes, (dialog, id) -> { pluginSwitcher.invoke();
pluginSwitcher.invoke(); SP.putBoolean("allow_hardware_pump", true);
SP.putBoolean("allow_hardware_pump", true); if (L.isEnabled(L.PUMP))
if (L.isEnabled(L.PUMP)) log.debug("First time HW pump allowed!");
log.debug("First time HW pump allowed!"); }).setNegativeButton(R.string.cancel, (dialog, id) -> {
}) pluginSwitcher.cancel();
.setNegativeButton(R.string.cancel, (dialog, id) -> { if (L.isEnabled(L.PUMP))
pluginSwitcher.cancel(); log.debug("User does not allow switching to HW pump!");
if (L.isEnabled(L.PUMP)) });
log.debug("User does not allow switching to HW pump!");
});
builder.create().show(); builder.create().show();
} }
} }
@ -152,26 +157,30 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
danaRSService = null; danaRSService = null;
} }
public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Service is connected"); log.debug("Service is connected");
DanaRSService.LocalBinder mLocalBinder = (DanaRSService.LocalBinder) service; DanaRSService.LocalBinder mLocalBinder = (DanaRSService.LocalBinder)service;
danaRSService = mLocalBinder.getServiceInstance(); danaRSService = mLocalBinder.getServiceInstance();
} }
}; };
@SuppressWarnings("UnusedParameters") @SuppressWarnings("UnusedParameters")
@Subscribe @Subscribe
public void onStatusEvent(final EventAppExit e) { public void onStatusEvent(final EventAppExit e) {
MainApp.instance().getApplicationContext().unbindService(mConnection); MainApp.instance().getApplicationContext().unbindService(mConnection);
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventDanaRSDeviceChange e) { public void onStatusEvent(final EventDanaRSDeviceChange e) {
mDeviceAddress = SP.getString(R.string.key_danars_address, ""); mDeviceAddress = SP.getString(R.string.key_danars_address, "");
mDeviceName = SP.getString(R.string.key_danars_name, ""); mDeviceName = SP.getString(R.string.key_danars_name, "");
} }
@Override @Override
public void connect(String from) { public void connect(String from) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -183,37 +192,46 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
@Override @Override
public boolean isConnected() { public boolean isConnected() {
return danaRSService != null && danaRSService.isConnected(); return danaRSService != null && danaRSService.isConnected();
} }
@Override @Override
public boolean isConnecting() { public boolean isConnecting() {
return danaRSService != null && danaRSService.isConnecting(); return danaRSService != null && danaRSService.isConnecting();
} }
@Override @Override
public boolean isHandshakeInProgress() { public boolean isHandshakeInProgress() {
return false; return false;
} }
@Override @Override
public void finishHandshaking() { public void finishHandshaking() {
} }
@Override @Override
public void disconnect(String from) { public void disconnect(String from) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("RS disconnect from: " + from); log.debug("RS disconnect from: " + from);
if (danaRSService != null) danaRSService.disconnect(from); if (danaRSService != null)
danaRSService.disconnect(from);
} }
@Override @Override
public void stopConnecting() { public void stopConnecting() {
if (danaRSService != null) danaRSService.stopConnecting(); if (danaRSService != null)
danaRSService.stopConnecting();
} }
@Override @Override
public void getPumpStatus() { public void getPumpStatus() {
if (danaRSService != null) { if (danaRSService != null) {
@ -223,6 +241,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
// DanaR interface // DanaR interface
@Override @Override
@ -230,28 +249,40 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return danaRSService.loadHistory(type); return danaRSService.loadHistory(type);
} }
@Override @Override
public PumpEnactResult loadEvents() { public PumpEnactResult loadEvents() {
return danaRSService.loadEvents(); return danaRSService.loadEvents();
} }
@Override @Override
public PumpEnactResult setUserOptions() { public PumpEnactResult setUserOptions() {
return danaRSService.setUserSettings(); return danaRSService.setUserSettings();
} }
// Constraints interface // Constraints interface
@Override @Override
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) { public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
absoluteRate.setIfSmaller(DanaRPump.getInstance().maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), DanaRPump.getInstance().maxBasal, MainApp.gs(R.string.pumplimit)), this); absoluteRate.setIfSmaller(
DanaRPump.getInstance().maxBasal,
String.format(MainApp.gs(R.string.limitingbasalratio), DanaRPump.getInstance().maxBasal,
MainApp.gs(R.string.pumplimit)), this);
return absoluteRate; return absoluteRate;
} }
@Override @Override
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) { public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); percentRate.setIfGreater(0,
percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)),
this);
percentRate.setIfSmaller(
getPumpDescription().maxTempPercent,
String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent,
MainApp.gs(R.string.pumplimit)), this);
return percentRate; return percentRate;
} }
@ -259,15 +290,20 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
@Override @Override
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) { public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
insulin.setIfSmaller(DanaRPump.getInstance().maxBolus, String.format(MainApp.gs(R.string.limitingbolus), DanaRPump.getInstance().maxBolus, MainApp.gs(R.string.pumplimit)), this); insulin.setIfSmaller(
DanaRPump.getInstance().maxBolus,
String.format(MainApp.gs(R.string.limitingbolus), DanaRPump.getInstance().maxBolus,
MainApp.gs(R.string.pumplimit)), this);
return insulin; return insulin;
} }
@Override @Override
public Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) { public Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) {
return applyBolusConstraints(insulin); return applyBolusConstraints(insulin);
} }
// Profile interface // Profile interface
@Nullable @Nullable
@ -278,16 +314,19 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return DanaRPump.getInstance().createConvertedProfile(); return DanaRPump.getInstance().createConvertedProfile();
} }
@Override @Override
public String getUnits() { public String getUnits() {
return DanaRPump.getInstance().getUnits(); return DanaRPump.getInstance().getUnits();
} }
@Override @Override
public String getProfileName() { public String getProfileName() {
return DanaRPump.getInstance().createConvertedProfileName(); return DanaRPump.getInstance().createConvertedProfileName();
} }
// Pump interface // Pump interface
@Override @Override
@ -295,17 +334,21 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return DanaRPump.getInstance().lastConnection > 0 && DanaRPump.getInstance().maxBasal > 0; return DanaRPump.getInstance().lastConnection > 0 && DanaRPump.getInstance().maxBasal > 0;
} }
@Override @Override
public boolean isSuspended() { public boolean isSuspended() {
return DanaRPump.getInstance().pumpSuspended; return DanaRPump.getInstance().pumpSuspended;
} }
@Override @Override
public boolean isBusy() { public boolean isBusy() {
if (danaRSService == null) return false; if (danaRSService == null)
return false;
return danaRSService.isConnected() || danaRSService.isConnecting(); return danaRSService.isConnected() || danaRSService.isConnecting();
} }
@Override @Override
public PumpEnactResult setNewBasalProfile(Profile profile) { public PumpEnactResult setNewBasalProfile(Profile profile) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -317,7 +360,8 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
if (!isInitialized()) { if (!isInitialized()) {
log.error("setNewBasalProfile not initialized"); log.error("setNewBasalProfile not initialized");
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED,
MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet); result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet);
return result; return result;
@ -325,14 +369,16 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
} }
if (!danaRSService.updateBasalsInPump(profile)) { if (!danaRSService.updateBasalsInPump(profile)) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE,
MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.failedupdatebasalprofile); result.comment = MainApp.gs(R.string.failedupdatebasalprofile);
return result; return result;
} else { } else {
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); Notification notification = new Notification(Notification.PROFILE_SET_OK,
MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.success = true; result.success = true;
result.enacted = true; result.enacted = true;
@ -341,6 +387,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
if (!isInitialized()) if (!isInitialized())
@ -352,8 +399,9 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60; int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
for (int h = 0; h < basalValues; h++) { for (int h = 0; h < basalValues; h++) {
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h]; Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
Double profileValue = profile.getBasalTimeFromMidnight((Integer) (h * basalIncrement)); Double profileValue = profile.getBasalTimeFromMidnight((Integer)(h * basalIncrement));
if (profileValue == null) return true; if (profileValue == null)
return true;
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) { if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue); log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
@ -363,19 +411,23 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return true; return true;
} }
@Override @Override
public long lastDataTime() { public long lastDataTime() {
return DanaRPump.getInstance().lastConnection; return DanaRPump.getInstance().lastConnection;
} }
@Override @Override
public double getBaseBasalRate() { public double getBaseBasalRate() {
return DanaRPump.getInstance().currentBasal; return DanaRPump.getInstance().currentBasal;
} }
@Override @Override
public synchronized PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { public synchronized PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); detailedBolusInfo.insulin = MainApp.getConstraintChecker()
.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0);
int speed = 12; int speed = 12;
@ -392,13 +444,14 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
// RS stores end time for bolus, we need to adjust time // RS stores end time for bolus, we need to adjust time
// default delivery speed is 12 sec/U // default delivery speed is 12 sec/U
detailedBolusInfo.date = DateUtil.now() + (long) (speed * detailedBolusInfo.insulin * 1000); detailedBolusInfo.date = DateUtil.now() + (long)(speed * detailedBolusInfo.insulin * 1000);
// clean carbs to prevent counting them as twice because they will picked up as another record // clean carbs to prevent counting them as twice because they will picked up as another record
// I don't think it's necessary to copy DetailedBolusInfo right now for carbs records // I don't think it's necessary to copy DetailedBolusInfo right now for carbs records
double carbs = detailedBolusInfo.carbs; double carbs = detailedBolusInfo.carbs;
detailedBolusInfo.carbs = 0; detailedBolusInfo.carbs = 0;
int carbTime = detailedBolusInfo.carbTime; int carbTime = detailedBolusInfo.carbTime;
if (carbTime == 0) carbTime--; // better set 1 min back to prevents clash with insulin if (carbTime == 0)
carbTime--; // better set 1 min back to prevents clash with insulin
detailedBolusInfo.carbTime = 0; detailedBolusInfo.carbTime = 0;
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
@ -407,15 +460,17 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
t.isSMB = detailedBolusInfo.isSMB; t.isSMB = detailedBolusInfo.isSMB;
boolean connectionOK = false; boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0) if (detailedBolusInfo.insulin > 0 || carbs > 0)
connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t); connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int)carbs,
DateUtil.now() + T.mins(carbTime).msecs(), t);
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep; result.success = connectionOK
&& Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep;
result.bolusDelivered = t.insulin; result.bolusDelivered = t.insulin;
result.carbsDelivered = detailedBolusInfo.carbs; result.carbsDelivered = detailedBolusInfo.carbs;
if (!result.success) { if (!result.success) {
String error = "" + DanaRS_Packet_Bolus_Set_Step_Bolus_Start.errorCode; String error = "" + DanaRS_Packet_Bolus_Set_Step_Bolus_Start.errorCode;
switch (DanaRS_Packet_Bolus_Set_Step_Bolus_Start.errorCode) { switch (DanaRS_Packet_Bolus_Set_Step_Bolus_Start.errorCode) {
// 4 reported as max bolus violation. Check later // 4 reported as max bolus violation. Check later
case 0x10: case 0x10:
error = MainApp.gs(R.string.maxbolusviolation); error = MainApp.gs(R.string.maxbolusviolation);
break; break;
@ -429,11 +484,13 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
error = MainApp.gs(R.string.insulinlimitviolation); error = MainApp.gs(R.string.insulinlimitviolation);
break; break;
} }
result.comment = String.format(MainApp.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, error); result.comment = String.format(MainApp.gs(R.string.boluserrorcode), detailedBolusInfo.insulin,
t.insulin, error);
} else } else
result.comment = MainApp.gs(R.string.virtualpump_resultok); result.comment = MainApp.gs(R.string.virtualpump_resultok);
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered); log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: "
+ result.bolusDelivered);
return result; return result;
} else { } else {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -446,6 +503,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
@Override @Override
public void stopBolusDelivering() { public void stopBolusDelivering() {
if (danaRSService == null) { if (danaRSService == null) {
@ -455,19 +513,22 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
danaRSService.bolusStop(); danaRSService.bolusStop();
} }
// This is called from APS // This is called from APS
@Override @Override
public synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) { public synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes,
Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min // Recheck pump status if older than 30 min
//This should not be needed while using queue because connection should be done before calling this // This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { // if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
// connect("setTempBasalAbsolute old data"); // connect("setTempBasalAbsolute old data");
//} // }
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile).value(); absoluteRate = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(absoluteRate), profile)
.value();
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate(); final boolean doLowTemp = absoluteRate < getBaseBasalRate();
@ -492,12 +553,15 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
if (doLowTemp || doHighTemp) { if (doLowTemp || doHighTemp) {
Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); if (percentRate < 100)
else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); percentRate = Round.ceilTo((double)percentRate, 10d).intValue();
else
percentRate = Round.floorTo((double)percentRate, 10d).intValue();
if (percentRate > 500) // Special high temp 500/15min if (percentRate > 500) // Special high temp 500/15min
percentRate = 500; percentRate = 500;
// Check if some temp is already in progress // Check if some temp is already in progress
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin()
.getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) { if (activeTemp != null) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("setTempBasalAbsolute: currently running: " + activeTemp.toString()); log.debug("setTempBasalAbsolute: currently running: " + activeTemp.toString());
@ -518,7 +582,8 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
// Convert duration from minutes to hours // Convert duration from minutes to hours
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes
+ " mins (doLowTemp || doHighTemp)");
if (percentRate == 0 && durationInMinutes > 30) { if (percentRate == 0 && durationInMinutes > 30) {
result = setTempBasalPercent(percentRate, durationInMinutes, profile, false); result = setTempBasalPercent(percentRate, durationInMinutes, profile, false);
} else { } else {
@ -540,11 +605,14 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return result; return result;
} }
@Override @Override
public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes,
Profile profile, boolean enforceNew) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile).value(); percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(percent), profile)
.value();
if (percent < 0) { if (percent < 0) {
result.isTempCancel = false; result.isTempCancel = false;
result.enacted = false; result.enacted = false;
@ -595,6 +663,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return result; return result;
} }
private synchronized PumpEnactResult setHighTempBasalPercent(Integer percent) { private synchronized PumpEnactResult setHighTempBasalPercent(Integer percent) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -618,6 +687,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return result; return result;
} }
@Override @Override
public synchronized PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { public synchronized PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
@ -636,11 +706,13 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
result.isPercent = false; result.isPercent = false;
result.isTempCancel = false; result.isTempCancel = false;
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount
+ " Asked: " + insulin);
return result; return result;
} }
boolean connectionOK = danaRSService.extendedBolus(insulin, durationInHalfHours); boolean connectionOK = danaRSService.extendedBolus(insulin, durationInHalfHours);
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAbsoluteRate - insulin) < getPumpDescription().extendedBolusStep) { if (connectionOK && pump.isExtendedInProgress
&& Math.abs(pump.extendedBolusAbsoluteRate - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = true; result.enacted = true;
result.success = true; result.success = true;
result.comment = MainApp.gs(R.string.virtualpump_resultok); result.comment = MainApp.gs(R.string.virtualpump_resultok);
@ -660,6 +732,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return result; return result;
} }
@Override @Override
public synchronized PumpEnactResult cancelTempBasal(boolean force) { public synchronized PumpEnactResult cancelTempBasal(boolean force) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -685,6 +758,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
@Override @Override
public synchronized PumpEnactResult cancelExtendedBolus() { public synchronized PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -708,6 +782,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
} }
} }
@Override @Override
public JSONObject getJSONStatus(Profile profile, String profileName) { public JSONObject getJSONStatus(Profile profile, String profileName) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
@ -750,7 +825,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
pumpjson.put("battery", battery); pumpjson.put("battery", battery);
pumpjson.put("status", status); pumpjson.put("status", status);
pumpjson.put("extended", extended); pumpjson.put("extended", extended);
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); pumpjson.put("reservoir", (int)pump.reservoirRemainingUnits);
pumpjson.put("clock", DateUtil.toISOString(now)); pumpjson.put("clock", DateUtil.toISOString(now));
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
@ -758,38 +833,45 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return pumpjson; return pumpjson;
} }
@Override @Override
public String deviceID() { public String deviceID() {
return DanaRPump.getInstance().serialNumber; return DanaRPump.getInstance().serialNumber;
} }
@Override @Override
public PumpDescription getPumpDescription() { public PumpDescription getPumpDescription() {
return pumpDescription; return pumpDescription;
} }
@Override @Override
public String shortStatus(boolean veryShort) { public String shortStatus(boolean veryShort) {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
String ret = ""; String ret = "";
if (pump.lastConnection != 0) { if (pump.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection; Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
int agoMin = (int) (agoMsec / 60d / 1000d); int agoMin = (int)(agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " minago\n"; ret += "LastConn: " + agoMin + " minago\n";
} }
if (pump.lastBolusTime != 0) { if (pump.lastBolusTime != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @"
+ android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
} }
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()); TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin()
.getRealTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) { if (activeTemp != null) {
ret += "Temp: " + activeTemp.toStringFull() + "\n"; ret += "Temp: " + activeTemp.toStringFull() + "\n";
} }
ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()); ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(
System.currentTimeMillis());
if (activeExtendedBolus != null) { if (activeExtendedBolus != null) {
ret += "Extended: " + activeExtendedBolus.toString() + "\n"; ret += "Extended: " + activeExtendedBolus.toString() + "\n";
} }
if (!veryShort) { if (!veryShort) {
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits
+ " U\n";
} }
ret += "IOB: " + pump.iob + "U\n"; ret += "IOB: " + pump.iob + "U\n";
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
@ -797,14 +879,27 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return ret; return ret;
} }
@Override @Override
public boolean isFakingTempsByExtendedBoluses() { public boolean isFakingTempsByExtendedBoluses() {
return false; return false;
} }
@Override @Override
public PumpEnactResult loadTDDs() { public PumpEnactResult loadTDDs() {
return loadHistory(RecordTypes.RECORD_TYPE_DAILY); return loadHistory(RecordTypes.RECORD_TYPE_DAILY);
} }
@Override
public List<CustomAction> getCustomActions() {
return null;
}
@Override
public PumpEnactResult executeCustomAction(CustomActionType customActionType) {
return null;
}
} }

View file

@ -1,18 +1,35 @@
package info.nightscout.androidaps.plugins.PumpInsight; package info.nightscout.androidaps.plugins.PumpInsight;
import android.content.DialogInterface; import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache.getRecordUniqueID;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity; import java.text.DecimalFormat;
import android.support.v7.app.AlertDialog; import java.util.ArrayList;
import java.util.List;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import sugar.free.sightparser.applayer.descriptors.ActiveBolus;
import java.util.ArrayList; import sugar.free.sightparser.applayer.descriptors.ActiveBolusType;
import java.util.List; import sugar.free.sightparser.applayer.descriptors.MessagePriority;
import sugar.free.sightparser.applayer.descriptors.PumpStatus;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock;
import sugar.free.sightparser.applayer.messages.AppLayerMessage;
import sugar.free.sightparser.applayer.messages.remote_control.BolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.ExtendedBolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.StandardBolusMessage;
import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
import sugar.free.sightparser.handling.SingleMessageTaskRunner;
import sugar.free.sightparser.handling.TaskRunner;
import sugar.free.sightparser.pipeline.Status;
import android.content.DialogInterface;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
@ -32,6 +49,8 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
@ -56,23 +75,6 @@ import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import sugar.free.sightparser.applayer.descriptors.ActiveBolus;
import sugar.free.sightparser.applayer.descriptors.ActiveBolusType;
import sugar.free.sightparser.applayer.descriptors.MessagePriority;
import sugar.free.sightparser.applayer.descriptors.PumpStatus;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock;
import sugar.free.sightparser.applayer.messages.AppLayerMessage;
import sugar.free.sightparser.applayer.messages.remote_control.BolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.ExtendedBolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.StandardBolusMessage;
import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
import sugar.free.sightparser.handling.SingleMessageTaskRunner;
import sugar.free.sightparser.handling.TaskRunner;
import sugar.free.sightparser.pipeline.Status;
import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache.getRecordUniqueID;
/** /**
* Created by jamorham on 23/01/2018. * Created by jamorham on 23/01/2018.
@ -86,10 +88,12 @@ import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache
@SuppressWarnings("AccessStaticViaInstance") @SuppressWarnings("AccessStaticViaInstance")
public class InsightPlugin extends PluginBase implements PumpInterface, ConstraintsInterface { public class InsightPlugin extends PluginBase implements PumpInterface, ConstraintsInterface {
private Logger log = LoggerFactory.getLogger(L.PUMP); private Logger log = LoggerFactory.getLogger(L.PUMP);
private static volatile InsightPlugin plugin; private static volatile InsightPlugin plugin;
public static InsightPlugin getPlugin() { public static InsightPlugin getPlugin() {
if (plugin == null) { if (plugin == null) {
plugin = new InsightPlugin(); plugin = new InsightPlugin();
@ -112,15 +116,11 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
private volatile boolean connector_enabled = false; private volatile boolean connector_enabled = false;
private List<BRProfileBlock.ProfileBlock> profileBlocks; private List<BRProfileBlock.ProfileBlock> profileBlocks;
private InsightPlugin() { private InsightPlugin() {
super(new PluginDescription() super(new PluginDescription().mainType(PluginType.PUMP).fragmentClass(InsightFragment.class.getName())
.mainType(PluginType.PUMP) .pluginName(R.string.insightpump).shortName(R.string.insightpump_shortname)
.fragmentClass(InsightFragment.class.getName()) .preferencesId(R.xml.pref_insightpump).description(R.string.description_pump_insight));
.pluginName(R.string.insightpump)
.shortName(R.string.insightpump_shortname)
.preferencesId(R.xml.pref_insightpump)
.description(R.string.description_pump_insight)
);
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("InsightPlugin instantiated"); log.debug("InsightPlugin instantiated");
pumpDescription.setPumpDescription(PumpType.AccuChekInsight); pumpDescription.setPumpDescription(PumpType.AccuChekInsight);
@ -132,10 +132,12 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
MainApp.bus().post(new EventInsightUpdateGui()); MainApp.bus().post(new EventInsightUpdateGui());
} }
private static void pushCallbackEvent(EventInsightCallback e) { private static void pushCallbackEvent(EventInsightCallback e) {
MainApp.bus().post(e); MainApp.bus().post(e);
} }
@Override @Override
protected void onStart() { protected void onStart() {
if (!connector_enabled) { if (!connector_enabled) {
@ -152,6 +154,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
super.onStart(); super.onStart();
} }
protected void onStop() { protected void onStop() {
if (connector_enabled) { if (connector_enabled) {
synchronized (this) { synchronized (this) {
@ -165,11 +168,13 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
@Override @Override
public boolean isFakingTempsByExtendedBoluses() { public boolean isFakingTempsByExtendedBoluses() {
return true; return true;
} }
@Override @Override
public PumpEnactResult loadTDDs() { public PumpEnactResult loadTDDs() {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -177,65 +182,76 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return result; return result;
} }
@Override @Override
public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher,
FragmentActivity context) {
boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
if (allowHardwarePump || context == null) { if (allowHardwarePump || context == null) {
pluginSwitcher.invoke(); pluginSwitcher.invoke();
} else { } else {
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.allow_hardware_pump_text) builder.setMessage(R.string.allow_hardware_pump_text)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
pluginSwitcher.invoke(); public void onClick(DialogInterface dialog, int id) {
SP.putBoolean("allow_hardware_pump", true); pluginSwitcher.invoke();
log.debug("First time HW pump allowed!"); SP.putBoolean("allow_hardware_pump", true);
} log.debug("First time HW pump allowed!");
}) }
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
pluginSwitcher.cancel(); public void onClick(DialogInterface dialog, int id) {
log.debug("User does not allow switching to HW pump!"); pluginSwitcher.cancel();
} log.debug("User does not allow switching to HW pump!");
}); }
});
builder.create().show(); builder.create().show();
} }
} }
@Override @Override
public boolean isInitialized() { public boolean isInitialized() {
return initialized; return initialized;
} }
@Override @Override
public boolean isSuspended() { public boolean isSuspended() {
return !isPumpRunning(); return !isPumpRunning();
} }
@Override @Override
public boolean isBusy() { public boolean isBusy() {
return false; return false;
} }
@Override @Override
public boolean isConnected() { public boolean isConnected() {
return Connector.get().isPumpConnected(); return Connector.get().isPumpConnected();
} }
@Override @Override
public boolean isConnecting() { public boolean isConnecting() {
return Connector.get().isPumpConnecting(); return Connector.get().isPumpConnecting();
} }
@Override @Override
public boolean isHandshakeInProgress() { public boolean isHandshakeInProgress() {
return false; return false;
} }
@Override @Override
public void finishHandshaking() { public void finishHandshaking() {
} }
@Override @Override
public void connect(String reason) { public void connect(String reason) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -260,6 +276,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
NSUpload.uploadDeviceStatus(); NSUpload.uploadDeviceStatus();
} }
@Override @Override
public void disconnect(String reason) { public void disconnect(String reason) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -278,6 +295,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
@Override @Override
public void stopConnecting() { public void stopConnecting() {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -301,6 +319,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
@Override @Override
public void getPumpStatus() { public void getPumpStatus() {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -309,7 +328,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("is connected.. requesting status"); log.debug("is connected.. requesting status");
try { try {
setStatusResult(fetchTaskRunner(new StatusTaskRunner(connector.getServiceConnector()), StatusTaskRunner.Result.class)); setStatusResult(fetchTaskRunner(new StatusTaskRunner(connector.getServiceConnector()),
StatusTaskRunner.Result.class));
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("GOT STATUS RESULT!!! PARTY WOOHOO!!!"); log.debug("GOT STATUS RESULT!!! PARTY WOOHOO!!!");
statusResultTime = Helpers.tsl(); statusResultTime = Helpers.tsl();
@ -319,7 +339,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
connector.requestHistorySync(); connector.requestHistorySync();
} catch (Exception e) { } catch (Exception e) {
log.error("StatusTaskRunner wasn't successful."); log.error("StatusTaskRunner wasn't successful.");
if (connector.getServiceConnector().isConnectedToService() && connector.getServiceConnector().getStatus() != Status.CONNECTED) { if (connector.getServiceConnector().isConnectedToService()
&& connector.getServiceConnector().getStatus() != Status.CONNECTED) {
if (Helpers.ratelimit("insight-reconnect", 2)) { if (Helpers.ratelimit("insight-reconnect", 2)) {
Connector.connectToPump(); Connector.connectToPump();
updateGui(); updateGui();
@ -332,18 +353,21 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
public void setStatusResult(StatusTaskRunner.Result result) { public void setStatusResult(StatusTaskRunner.Result result) {
this.statusResult = result; this.statusResult = result;
this.pumpDescription.basalMinimumRate = result.minimumBasalAmount; this.pumpDescription.basalMinimumRate = result.minimumBasalAmount;
this.pumpDescription.basalMaximumRate = result.maximumBasalAmount; this.pumpDescription.basalMaximumRate = result.maximumBasalAmount;
} }
@Override @Override
public PumpEnactResult setNewBasalProfile(Profile profile) { public PumpEnactResult setNewBasalProfile(Profile profile) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
if (!isInitialized()) { if (!isInitialized()) {
log.error("setNewBasalProfile not initialized"); log.error("setNewBasalProfile not initialized");
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED,
MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet); result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet);
return result; return result;
@ -355,31 +379,41 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
Profile.BasalValue nextValue = null; Profile.BasalValue nextValue = null;
if (profile.getBasalValues().length > i + 1) if (profile.getBasalValues().length > i + 1)
nextValue = profile.getBasalValues()[i + 1]; nextValue = profile.getBasalValues()[i + 1];
profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), Helpers.roundDouble(basalValue.value, 2))); profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds
: 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), Helpers.roundDouble(basalValue.value, 2)));
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("setNewBasalProfile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); log.debug("setNewBasalProfile: "
+ basalValue.value
+ " for "
+ Integer
.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60));
} }
try { try {
fetchTaskRunner(new WriteBasalProfileTaskRunner(connector.getServiceConnector(), profileBlocks)); fetchTaskRunner(new WriteBasalProfileTaskRunner(connector.getServiceConnector(), profileBlocks));
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); Notification notification = new Notification(Notification.PROFILE_SET_OK,
MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.success = true; result.success = true;
result.enacted = true; result.enacted = true;
result.comment = "OK"; result.comment = "OK";
this.profileBlocks = profileBlocks; this.profileBlocks = profileBlocks;
} catch (Exception e) { } catch (Exception e) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE,
MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.failedupdatebasalprofile); result.comment = MainApp.gs(R.string.failedupdatebasalprofile);
} }
return result; return result;
} }
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
if (!isInitialized() || profileBlocks == null) return true; if (!isInitialized() || profileBlocks == null)
if (profile.getBasalValues().length != profileBlocks.size()) return false; return true;
if (profile.getBasalValues().length != profileBlocks.size())
return false;
for (int i = 0; i < profileBlocks.size(); i++) { for (int i = 0; i < profileBlocks.size(); i++) {
BRProfileBlock.ProfileBlock profileBlock = profileBlocks.get(i); BRProfileBlock.ProfileBlock profileBlock = profileBlocks.get(i);
Profile.BasalValue basalValue = profile.getBasalValues()[i]; Profile.BasalValue basalValue = profile.getBasalValues()[i];
@ -387,32 +421,44 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
if (profile.getBasalValues().length > i + 1) if (profile.getBasalValues().length > i + 1)
nextValue = profile.getBasalValues()[i + 1]; nextValue = profile.getBasalValues()[i + 1];
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("isThisProfileSet - Comparing block: Pump: " + profileBlock.getAmount() + " for " + profileBlock.getDuration() log.debug("isThisProfileSet - Comparing block: Pump: "
+ " Profile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); + profileBlock.getAmount()
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) + " for "
+ profileBlock.getDuration()
+ " Profile: "
+ basalValue.value
+ " for "
+ Integer
.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60));
if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60)
- basalValue.timeAsSeconds)
return false; return false;
//Allow a little imprecision due to rounding errors // Allow a little imprecision due to rounding errors
if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D) if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D)
return false; return false;
} }
return true; return true;
} }
@Override @Override
public long lastDataTime() { public long lastDataTime() {
return lastDataTime; return lastDataTime;
} }
@Override @Override
public double getBaseBasalRate() { public double getBaseBasalRate() {
return basalRate; return basalRate;
} }
public String getBaseBasalRateString() { public String getBaseBasalRateString() {
final DecimalFormat df = new DecimalFormat("#.##"); final DecimalFormat df = new DecimalFormat("#.##");
return df.format(basalRate); return df.format(basalRate);
} }
@Override @Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
final PumpEnactResult result = new PumpEnactResult(); final PumpEnactResult result = new PumpEnactResult();
@ -457,39 +503,50 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result); log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: "
+ detailedBolusInfo.carbs + "g " + result);
updateGui(); updateGui();
connector.tryToGetPumpStatusAgain(); connector.tryToGetPumpStatusAgain();
if (result.success) while (true) { if (result.success)
try { while (true) {
Thread.sleep(500); try {
final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); Thread.sleep(500);
ActiveBolusesMessage activeBolusesMessage = fetchSingleMessage(new ActiveBolusesMessage(), ActiveBolusesMessage.class); final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
ActiveBolus activeBolus = null; ActiveBolusesMessage activeBolusesMessage = fetchSingleMessage(new ActiveBolusesMessage(),
if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId) ActiveBolusesMessage.class);
activeBolus = activeBolusesMessage.getBolus1(); ActiveBolus activeBolus = null;
else if (activeBolusesMessage.getBolus2() != null && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId) if (activeBolusesMessage.getBolus1() != null
activeBolus = activeBolusesMessage.getBolus2(); && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId)
else if (activeBolusesMessage.getBolus3() != null && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId) activeBolus = activeBolusesMessage.getBolus1();
activeBolus = activeBolusesMessage.getBolus3(); else if (activeBolusesMessage.getBolus2() != null
if (activeBolus == null) break; && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId)
else { activeBolus = activeBolusesMessage.getBolus2();
int percentBefore = bolusingEvent.percent; else if (activeBolusesMessage.getBolus3() != null
bolusingEvent.percent = (int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount())); && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId)
bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount()); activeBolus = activeBolusesMessage.getBolus3();
if (percentBefore != bolusingEvent.percent) MainApp.bus().post(bolusingEvent); if (activeBolus == null)
break;
else {
int percentBefore = bolusingEvent.percent;
bolusingEvent.percent = (int)(100D / activeBolus.getInitialAmount() * (activeBolus
.getInitialAmount() - activeBolus.getLeftoverAmount()));
bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering),
activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount());
if (percentBefore != bolusingEvent.percent)
MainApp.bus().post(bolusingEvent);
}
} catch (Exception e) {
break;
} }
} catch (Exception e) {
break;
} }
}
connector.requestHistorySync(2000); connector.requestHistorySync(2000);
return result; return result;
} }
@Override @Override
public void stopBolusDelivering() { public void stopBolusDelivering() {
CancelBolusMessage cancelBolusMessage = new CancelBolusMessage(); CancelBolusMessage cancelBolusMessage = new CancelBolusMessage();
@ -501,10 +558,12 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
// Temporary Basals // Temporary Basals
@Override @Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Set TBR absolute: " + absoluteRate); log.debug("Set TBR absolute: " + absoluteRate);
if (getBaseBasalRate() == 0) { if (getBaseBasalRate() == 0) {
@ -514,24 +573,27 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
double percent = 100D / getBaseBasalRate() * absoluteRate; double percent = 100D / getBaseBasalRate() * absoluteRate;
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Calculated requested rate: " + absoluteRate + " base rate: " + getBaseBasalRate() + " percentage: " + percent + "%"); log.debug("Calculated requested rate: " + absoluteRate + " base rate: " + getBaseBasalRate()
+ " percentage: " + percent + "%");
try { try {
if (percent > 250) { if (percent > 250) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Calculated rate is above 250%, switching to emulation using extended boluses"); log.debug("Calculated rate is above 250%, switching to emulation using extended boluses");
cancelTempBasal(true); cancelTempBasal(true);
if (!setExtendedBolus((absoluteRate - getBaseBasalRate()) / 60D * ((double) durationInMinutes), durationInMinutes).success) { if (!setExtendedBolus((absoluteRate - getBaseBasalRate()) / 60D * ((double)durationInMinutes),
//Fallback to TBR if setting an extended bolus didn't work durationInMinutes).success) {
// Fallback to TBR if setting an extended bolus didn't work
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Setting an extended bolus didn't work, falling back to normal TBR"); log.debug("Setting an extended bolus didn't work, falling back to normal TBR");
return setTempBasalPercent((int) percent, durationInMinutes, profile, true); return setTempBasalPercent((int)percent, durationInMinutes, profile, true);
} }
return new PumpEnactResult().success(true).enacted(true).absolute(absoluteRate).duration(durationInMinutes); return new PumpEnactResult().success(true).enacted(true).absolute(absoluteRate)
.duration(durationInMinutes);
} else { } else {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Calculated rate is below or equal to 250%, using normal TBRs"); log.debug("Calculated rate is below or equal to 250%, using normal TBRs");
cancelExtendedBolus(); cancelExtendedBolus();
return setTempBasalPercent((int) percent, durationInMinutes, profile, true); return setTempBasalPercent((int)percent, durationInMinutes, profile, true);
} }
} catch (Exception e) { } catch (Exception e) {
return pumpEnactFailure(); return pumpEnactFailure();
@ -540,23 +602,22 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
@Override @Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Set TBR %"); log.debug("Set TBR %");
percent = (int) Math.round(((double) percent) / 10d) * 10; percent = (int)Math.round(((double)percent) / 10d) * 10;
if (percent == 100) { if (percent == 100) {
// This would cause a cancel if a tbr is in progress so treat as a cancel // This would cause a cancel if a tbr is in progress so treat as a cancel
return cancelTempBasal(false); return cancelTempBasal(false);
} else if (percent > 250) percent = 250; } else if (percent > 250)
percent = 250;
try { try {
fetchTaskRunner(new SetTBRTaskRunner(connector.getServiceConnector(), percent, durationInMinutes)); fetchTaskRunner(new SetTBRTaskRunner(connector.getServiceConnector(), percent, durationInMinutes));
final TemporaryBasal tempBasal = new TemporaryBasal() final TemporaryBasal tempBasal = new TemporaryBasal().date(System.currentTimeMillis()).percent(percent)
.date(System.currentTimeMillis()) .duration(durationInMinutes).source(Source.USER);
.percent(percent)
.duration(durationInMinutes)
.source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal); TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
updateGui(); updateGui();
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -589,8 +650,10 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
private void realTBRCancel() throws Exception { private void realTBRCancel() throws Exception {
if (fetchTaskRunner(new CancelTBRSilentlyTaskRunner(connector.getServiceConnector()), Boolean.class) && TreatmentsPlugin.getPlugin().isTempBasalInProgress()) { if (fetchTaskRunner(new CancelTBRSilentlyTaskRunner(connector.getServiceConnector()), Boolean.class)
&& TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER); TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop); TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop);
} }
@ -608,22 +671,21 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
extendedBolusMessage.setAmount(insulin); extendedBolusMessage.setAmount(insulin);
extendedBolusMessage.setDuration(durationInMinutes); extendedBolusMessage.setDuration(durationInMinutes);
BolusMessage bolusMessage = fetchSingleMessage(extendedBolusMessage, BolusMessage.class); BolusMessage bolusMessage = fetchSingleMessage(extendedBolusMessage, BolusMessage.class);
final ExtendedBolus extendedBolus = new ExtendedBolus() final ExtendedBolus extendedBolus = new ExtendedBolus().date(System.currentTimeMillis()).insulin(insulin)
.date(System.currentTimeMillis()) .durationInMinutes(durationInMinutes).source(Source.USER)
.insulin(insulin) .pumpId(getRecordUniqueID(bolusMessage.getBolusId()));
.durationInMinutes(durationInMinutes)
.source(Source.USER)
.pumpId(getRecordUniqueID(bolusMessage.getBolusId()));
TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
updateGui(); updateGui();
connector.requestHistorySync(30000); connector.requestHistorySync(30000);
connector.tryToGetPumpStatusAgain(); connector.tryToGetPumpStatusAgain();
return new PumpEnactResult().success(true).enacted(true).duration(durationInMinutes).bolusDelivered(insulin); return new PumpEnactResult().success(true).enacted(true).duration(durationInMinutes)
.bolusDelivered(insulin);
} catch (Exception e) { } catch (Exception e) {
return pumpEnactFailure(); return pumpEnactFailure();
} }
} }
@Override @Override
public PumpEnactResult cancelExtendedBolus() { public PumpEnactResult cancelExtendedBolus() {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
@ -632,13 +694,15 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
Integer bolusId = null; Integer bolusId = null;
try { try {
bolusId = fetchTaskRunner(new CancelBolusSilentlyTaskRunner(connector.getServiceConnector(), ActiveBolusType.EXTENDED), Integer.class); bolusId = fetchTaskRunner(new CancelBolusSilentlyTaskRunner(connector.getServiceConnector(),
ActiveBolusType.EXTENDED), Integer.class);
if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
ExtendedBolus exStop = new ExtendedBolus(System.currentTimeMillis()); ExtendedBolus exStop = new ExtendedBolus(System.currentTimeMillis());
exStop.source = Source.USER; exStop.source = Source.USER;
TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(exStop); TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(exStop);
} }
if (bolusId != null) connector.requestHistorySync(5000); if (bolusId != null)
connector.requestHistorySync(5000);
connector.tryToGetPumpStatusAgain(); connector.tryToGetPumpStatusAgain();
updateGui(); updateGui();
return new PumpEnactResult().success(true).enacted(bolusId != null); return new PumpEnactResult().success(true).enacted(bolusId != null);
@ -658,6 +722,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return fetchSingleMessage(message, BolusMessage.class).getBolusId(); return fetchSingleMessage(message, BolusMessage.class).getBolusId();
} }
@Override @Override
public JSONObject getJSONStatus(Profile profile, String profileName) { public JSONObject getJSONStatus(Profile profile, String profileName) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -706,44 +771,53 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return pump; return pump;
} }
@Override @Override
public String deviceID() { public String deviceID() {
return "InsightPump"; return "InsightPump";
} }
@Override @Override
public PumpDescription getPumpDescription() { public PumpDescription getPumpDescription() {
return pumpDescription; return pumpDescription;
} }
@Override @Override
public String shortStatus(boolean veryShort) { public String shortStatus(boolean veryShort) {
String msg = gs(R.string.insightpump_shortname) + " Batt: " + batteryPercent + " Reserv: " + reservoirInUnits + " Basal: " + basalRate; String msg = gs(R.string.insightpump_shortname) + " Batt: " + batteryPercent + " Reserv: " + reservoirInUnits
+ " Basal: " + basalRate;
if (LiveHistory.getStatus().length() > 0) { if (LiveHistory.getStatus().length() > 0) {
msg += LiveHistory.getStatus(); msg += LiveHistory.getStatus();
} }
return msg; return msg;
} }
private void processStatusResult() { private void processStatusResult() {
if (statusResult != null) { if (statusResult != null) {
batteryPercent = statusResult.battery; batteryPercent = statusResult.battery;
reservoirInUnits = (int) statusResult.cartridge; reservoirInUnits = (int)statusResult.cartridge;
basalRate = statusResult.baseBasalRate; basalRate = statusResult.baseBasalRate;
profileBlocks = statusResult.basalProfile; profileBlocks = statusResult.basalProfile;
initialized = true; // basic communication test initialized = true; // basic communication test
} }
} }
private String gs(int id) { private String gs(int id) {
return MainApp.gs(id); return MainApp.gs(id);
} }
private boolean isPumpRunning() { private boolean isPumpRunning() {
if (statusResult == null) return true; // assume running if we have no information if (statusResult == null)
return true; // assume running if we have no information
return statusResult.pumpStatus == PumpStatus.STARTED; return statusResult.pumpStatus == PumpStatus.STARTED;
} }
List<StatusItem> getStatusItems(boolean refresh) { List<StatusItem> getStatusItems(boolean refresh) {
final List<StatusItem> l = new ArrayList<>(); final List<StatusItem> l = new ArrayList<>();
@ -760,7 +834,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
if (pumpRunning) { if (pumpRunning) {
l.add(new StatusItem(gs(R.string.pump_basebasalrate_label), getBaseBasalRateString() + "U")); l.add(new StatusItem(gs(R.string.pump_basebasalrate_label), getBaseBasalRateString() + "U"));
} else { } else {
l.add(new StatusItem(gs(R.string.combo_warning), gs(R.string.pump_stopped_uppercase), StatusItem.Highlight.CRITICAL)); l.add(new StatusItem(gs(R.string.combo_warning), gs(R.string.pump_stopped_uppercase),
StatusItem.Highlight.CRITICAL));
} }
} }
@ -768,17 +843,17 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
final long offset_minutes = offset_ms / 60000; final long offset_minutes = offset_ms / 60000;
if (statusResult != null) { if (statusResult != null) {
l.add(new StatusItem(gs(R.string.status_updated), Helpers.niceTimeScalar(Helpers.msSince(statusResultTime)) + " " + gs(R.string.ago))); l.add(new StatusItem(gs(R.string.status_updated), Helpers.niceTimeScalar(Helpers.msSince(statusResultTime))
l.add(new StatusItem(gs(R.string.pump_battery_label), batteryPercent + "%", batteryPercent < 100 ? + " " + gs(R.string.ago)));
(batteryPercent < 90 ? l.add(new StatusItem(gs(R.string.pump_battery_label), batteryPercent + "%",
(batteryPercent < 70 ? batteryPercent < 100 ? (batteryPercent < 90 ? (batteryPercent < 70 ? (StatusItem.Highlight.BAD)
(StatusItem.Highlight.BAD) : StatusItem.Highlight.NOTICE) : StatusItem.Highlight.NORMAL) : StatusItem.Highlight.GOOD)); : StatusItem.Highlight.NOTICE) : StatusItem.Highlight.NORMAL) : StatusItem.Highlight.GOOD));
l.add(new StatusItem(gs(R.string.pump_reservoir_label), reservoirInUnits + "U")); l.add(new StatusItem(gs(R.string.pump_reservoir_label), reservoirInUnits + "U"));
try { try {
if (statusResult.tbrAmount != 100) { if (statusResult.tbrAmount != 100) {
l.add(new StatusItem(gs(R.string.insight_active_tbr), statusResult.tbrAmount + "% " + gs(R.string.with) + " " l.add(new StatusItem(gs(R.string.insight_active_tbr), statusResult.tbrAmount + "% "
+ Helpers.qs(statusResult.tbrLeftoverDuration - offset_minutes, 0) + gs(R.string.with) + " " + Helpers.qs(statusResult.tbrLeftoverDuration - offset_minutes, 0)
+ " " + gs(R.string.insight_min_left), StatusItem.Highlight.NOTICE)); + " " + gs(R.string.insight_min_left), StatusItem.Highlight.NOTICE));
} }
} catch (NullPointerException e) { } catch (NullPointerException e) {
// currentTBRMessage may be null // currentTBRMessage may be null
@ -788,7 +863,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) { if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
try { try {
l.add(new StatusItem(gs(R.string.pump_tempbasal_label), TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull())); l.add(new StatusItem(gs(R.string.pump_tempbasal_label), TreatmentsPlugin.getPlugin()
.getTempBasalFromHistory(System.currentTimeMillis()).toStringFull()));
} catch (NullPointerException e) { } catch (NullPointerException e) {
// //
} }
@ -807,7 +883,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
try { try {
l.add(new StatusItem(gs(R.string.virtualpump_extendedbolus_label), TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()).toString())); l.add(new StatusItem(gs(R.string.virtualpump_extendedbolus_label), TreatmentsPlugin.getPlugin()
.getExtendedBolusFromHistory(System.currentTimeMillis()).toString()));
} catch (NullPointerException e) { } catch (NullPointerException e) {
// //
} }
@ -833,15 +910,18 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
connector.tryToGetPumpStatusAgain(); connector.tryToGetPumpStatusAgain();
} }
connector.requestHistorySync(); connector.requestHistorySync();
if (refresh) scheduleGUIUpdate(); if (refresh)
scheduleGUIUpdate();
return l; return l;
} }
private synchronized void scheduleGUIUpdate() { private synchronized void scheduleGUIUpdate() {
if (!update_pending && connector.uiFresh()) { if (!update_pending && connector.uiFresh()) {
update_pending = true; update_pending = true;
Helpers.runOnUiThreadDelayed(new Runnable() { Helpers.runOnUiThreadDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
updateGui(); updateGui();
@ -850,20 +930,41 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
private void statusActiveBolus(ActiveBolus activeBolus, long offset_mins, List<StatusItem> l) { private void statusActiveBolus(ActiveBolus activeBolus, long offset_mins, List<StatusItem> l) {
if (activeBolus == null) return; if (activeBolus == null)
return;
switch (activeBolus.getBolusType()) { switch (activeBolus.getBolusType()) {
case STANDARD: case STANDARD:
l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus.getInitialAmount() + "U", StatusItem.Highlight.NOTICE)); l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus
.getInitialAmount() + "U", StatusItem.Highlight.NOTICE));
break; break;
case EXTENDED: case EXTENDED:
l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus.getInitialAmount() + "U " + gs(R.string.insight_total_with) + " " l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus
+ activeBolus.getLeftoverAmount() + "U " + gs(R.string.insight_remaining_over) + " " + (activeBolus.getDuration() - offset_mins) + " " + gs(R.string.insight_min), StatusItem.Highlight.NOTICE)); .getInitialAmount()
+ "U "
+ gs(R.string.insight_total_with)
+ " "
+ activeBolus.getLeftoverAmount()
+ "U "
+ gs(R.string.insight_remaining_over)
+ " "
+ (activeBolus.getDuration() - offset_mins) + " " + gs(R.string.insight_min),
StatusItem.Highlight.NOTICE));
break; break;
case MULTIWAVE: case MULTIWAVE:
l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus.getInitialAmount() + "U " + gs(R.string.insight_upfront_with) + " " l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus
+ activeBolus.getLeftoverAmount() + "U " + gs(R.string.insight_remaining_over) + " " + (activeBolus.getDuration() - offset_mins) + " " + gs(R.string.insight_min), StatusItem.Highlight.NOTICE)); .getInitialAmount()
+ "U "
+ gs(R.string.insight_upfront_with)
+ " "
+ activeBolus.getLeftoverAmount()
+ "U "
+ gs(R.string.insight_remaining_over)
+ " "
+ (activeBolus.getDuration() - offset_mins) + " " + gs(R.string.insight_min),
StatusItem.Highlight.NOTICE));
break; break;
default: default:
@ -871,32 +972,40 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
} }
} }
private void fetchTaskRunner(TaskRunner taskRunner) throws Exception { private void fetchTaskRunner(TaskRunner taskRunner) throws Exception {
fetchTaskRunner(taskRunner, Object.class); fetchTaskRunner(taskRunner, Object.class);
} }
private void fetchSingleMessage(AppLayerMessage message) throws Exception { private void fetchSingleMessage(AppLayerMessage message) throws Exception {
fetchSingleMessage(message, AppLayerMessage.class); fetchSingleMessage(message, AppLayerMessage.class);
} }
private <T> T fetchTaskRunner(TaskRunner taskRunner, Class<T> resultType) throws Exception { private <T> T fetchTaskRunner(TaskRunner taskRunner, Class<T> resultType) throws Exception {
try { try {
T result = (T) taskRunner.fetchAndWaitUsingLatch(BUSY_WAIT_TIME); T result = (T)taskRunner.fetchAndWaitUsingLatch(BUSY_WAIT_TIME);
lastDataTime = System.currentTimeMillis(); lastDataTime = System.currentTimeMillis();
return result; return result;
} catch (Exception e) { } catch (Exception e) {
log.error("Error while fetching " + taskRunner.getClass().getSimpleName() + ": " + e.getClass().getSimpleName()); log.error("Error while fetching " + taskRunner.getClass().getSimpleName() + ": "
+ e.getClass().getSimpleName());
throw e; throw e;
} }
} }
private <T extends AppLayerMessage> T fetchSingleMessage(AppLayerMessage message, Class<T> resultType) throws Exception {
private <T extends AppLayerMessage> T fetchSingleMessage(AppLayerMessage message, Class<T> resultType)
throws Exception {
try { try {
T result = (T) new SingleMessageTaskRunner(connector.getServiceConnector(), message).fetchAndWaitUsingLatch(BUSY_WAIT_TIME); T result = (T)new SingleMessageTaskRunner(connector.getServiceConnector(), message)
.fetchAndWaitUsingLatch(BUSY_WAIT_TIME);
lastDataTime = System.currentTimeMillis(); lastDataTime = System.currentTimeMillis();
return result; return result;
} catch (Exception e) { } catch (Exception e) {
log.error("Error while fetching " + message.getClass().getSimpleName() + ": " + e.getClass().getSimpleName()); log.error("Error while fetching " + message.getClass().getSimpleName() + ": "
+ e.getClass().getSimpleName());
throw e; throw e;
} }
} }
@ -906,30 +1015,54 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return new PumpEnactResult().success(false).enacted(false); return new PumpEnactResult().success(false).enacted(false);
} }
// Constraints // Constraints
@Override @Override
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) { public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); percentRate.setIfGreater(0,
percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)),
this);
percentRate.setIfSmaller(
getPumpDescription().maxTempPercent,
String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent,
MainApp.gs(R.string.pumplimit)), this);
return percentRate; return percentRate;
} }
@Override @Override
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) { public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
if (statusResult != null) { if (statusResult != null) {
insulin.setIfSmaller(statusResult.maximumBolusAmount, String.format(MainApp.gs(R.string.limitingbolus), statusResult.maximumBolusAmount, MainApp.gs(R.string.pumplimit)), this); insulin.setIfSmaller(
statusResult.maximumBolusAmount,
String.format(MainApp.gs(R.string.limitingbolus), statusResult.maximumBolusAmount,
MainApp.gs(R.string.pumplimit)), this);
if (insulin.value() < statusResult.minimumBolusAmount) { if (insulin.value() < statusResult.minimumBolusAmount) {
//TODO: Add function to Constraints or use different approach // TODO: Add function to Constraints or use different approach
// This only works if the interface of the InsightPlugin is called last. // This only works if the interface of the InsightPlugin is called last.
// If not, another contraint could theoretically set the value between 0 and minimumBolusAmount // If not, another contraint could theoretically set the value between 0 and minimumBolusAmount
insulin.set(0d, String.format(MainApp.gs(R.string.limitingbolus), statusResult.minimumBolusAmount, MainApp.gs(R.string.pumplimit)), this); insulin.set(
0d,
String.format(MainApp.gs(R.string.limitingbolus), statusResult.minimumBolusAmount,
MainApp.gs(R.string.pumplimit)), this);
} }
} }
return insulin; return insulin;
} }
@Override
public List<CustomAction> getCustomActions() {
return null;
}
@Override
public PumpEnactResult executeCustomAction(CustomActionType customActionType) {
return null;
}
} }

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.plugins.PumpMDI; package info.nightscout.androidaps.plugins.PumpMDI;
import java.util.List;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -17,6 +19,8 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -24,10 +28,12 @@ import info.nightscout.utils.DateUtil;
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class MDIPlugin extends PluginBase implements PumpInterface { public class MDIPlugin extends PluginBase implements PumpInterface {
private static Logger log = LoggerFactory.getLogger(MDIPlugin.class); private static Logger log = LoggerFactory.getLogger(MDIPlugin.class);
private static MDIPlugin plugin = null; private static MDIPlugin plugin = null;
public static MDIPlugin getPlugin() { public static MDIPlugin getPlugin() {
if (plugin == null) if (plugin == null)
plugin = new MDIPlugin(); plugin = new MDIPlugin();
@ -36,12 +42,10 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
private PumpDescription pumpDescription = new PumpDescription(); private PumpDescription pumpDescription = new PumpDescription();
private MDIPlugin() { private MDIPlugin() {
super(new PluginDescription() super(new PluginDescription().mainType(PluginType.PUMP).pluginName(R.string.mdi)
.mainType(PluginType.PUMP) .description(R.string.description_pump_mdi));
.pluginName(R.string.mdi)
.description(R.string.description_pump_mdi)
);
pumpDescription.isBolusCapable = true; pumpDescription.isBolusCapable = true;
pumpDescription.bolusStep = 0.5d; pumpDescription.bolusStep = 0.5d;
@ -51,68 +55,82 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
pumpDescription.isRefillingCapable = false; pumpDescription.isRefillingCapable = false;
} }
@Override @Override
public boolean isFakingTempsByExtendedBoluses() { public boolean isFakingTempsByExtendedBoluses() {
return false; return false;
} }
@Override @Override
public PumpEnactResult loadTDDs() { public PumpEnactResult loadTDDs() {
//no result, could read DB in the future? // no result, could read DB in the future?
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
return result; return result;
} }
@Override @Override
public boolean isInitialized() { public boolean isInitialized() {
return true; return true;
} }
@Override @Override
public boolean isSuspended() { public boolean isSuspended() {
return false; return false;
} }
@Override @Override
public boolean isBusy() { public boolean isBusy() {
return false; return false;
} }
@Override @Override
public boolean isConnected() { public boolean isConnected() {
return true; return true;
} }
@Override @Override
public boolean isConnecting() { public boolean isConnecting() {
return false; return false;
} }
@Override @Override
public boolean isHandshakeInProgress() { public boolean isHandshakeInProgress() {
return false; return false;
} }
@Override @Override
public void finishHandshaking() { public void finishHandshaking() {
} }
@Override @Override
public void connect(String reason) { public void connect(String reason) {
} }
@Override @Override
public void disconnect(String reason) { public void disconnect(String reason) {
} }
@Override @Override
public void stopConnecting() { public void stopConnecting() {
} }
@Override @Override
public void getPumpStatus() { public void getPumpStatus() {
} }
@Override @Override
public PumpEnactResult setNewBasalProfile(Profile profile) { public PumpEnactResult setNewBasalProfile(Profile profile) {
// Do nothing here. we are using ConfigBuilderPlugin.getPlugin().getActiveProfile().getProfile(); // Do nothing here. we are using ConfigBuilderPlugin.getPlugin().getActiveProfile().getProfile();
@ -121,21 +139,25 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
return false; return false;
} }
@Override @Override
public long lastDataTime() { public long lastDataTime() {
return System.currentTimeMillis(); return System.currentTimeMillis();
} }
@Override @Override
public double getBaseBasalRate() { public double getBaseBasalRate() {
return 0d; return 0d;
} }
@Override @Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -147,12 +169,15 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public void stopBolusDelivering() { public void stopBolusDelivering() {
} }
@Override @Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = false; result.success = false;
result.comment = MainApp.gs(R.string.pumperror); result.comment = MainApp.gs(R.string.pumperror);
@ -161,8 +186,10 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = false; result.success = false;
result.comment = MainApp.gs(R.string.pumperror); result.comment = MainApp.gs(R.string.pumperror);
@ -171,6 +198,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -181,6 +209,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult cancelTempBasal(boolean force) { public PumpEnactResult cancelTempBasal(boolean force) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -191,6 +220,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult cancelExtendedBolus() { public PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -201,6 +231,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public JSONObject getJSONStatus(Profile profile, String profileName) { public JSONObject getJSONStatus(Profile profile, String profileName) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -224,19 +255,33 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
return pump; return pump;
} }
@Override @Override
public String deviceID() { public String deviceID() {
return "MDI"; return "MDI";
} }
@Override @Override
public PumpDescription getPumpDescription() { public PumpDescription getPumpDescription() {
return pumpDescription; return pumpDescription;
} }
@Override @Override
public String shortStatus(boolean veryShort) { public String shortStatus(boolean veryShort) {
return deviceID(); return deviceID();
} }
@Override
public List<CustomAction> getCustomActions() {
return null;
}
@Override
public PumpEnactResult executeCustomAction(CustomActionType customActionType) {
return null;
}
} }

View file

@ -214,7 +214,7 @@ public class MedtronicFragment extends SubscriberFragment {
} }
private void setDeviceStatus(MedtronicPumpStatus pumpStatus) { private synchronized void setDeviceStatus(MedtronicPumpStatus pumpStatus) {
pumpStatus.rileyLinkServiceState = (RileyLinkServiceState)checkStatusSet(pumpStatus.rileyLinkServiceState, pumpStatus.rileyLinkServiceState = (RileyLinkServiceState)checkStatusSet(pumpStatus.rileyLinkServiceState,
RileyLinkUtil.getServiceState()); RileyLinkUtil.getServiceState());
@ -270,8 +270,10 @@ public class MedtronicFragment extends SubscriberFragment {
case Active: { case Active: {
MedtronicCommandType cmd = MedtronicUtil.getCurrentCommand(); MedtronicCommandType cmd = MedtronicUtil.getCurrentCommand();
LOG.debug("Command: " + cmd);
if (cmd == null) if (cmd == null)
pumpStatusIconView.setText(" " + pumpStatus.pumpDeviceState.name()); pumpStatusIconView.setText(" " + MainApp.gs(pumpStatus.pumpDeviceState.getResourceId()));
else else
pumpStatusIconView.setText(" " + cmd.name()); pumpStatusIconView.setText(" " + cmd.name());

View file

@ -1,8 +1,12 @@
package info.nightscout.androidaps.plugins.PumpMedtronic; package info.nightscout.androidaps.plugins.PumpMedtronic;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDateTime; import org.joda.time.LocalDateTime;
@ -16,6 +20,8 @@ import android.os.SystemClock;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -24,12 +30,14 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpCommon.PumpPluginAbstract; import info.nightscout.androidaps.plugins.PumpCommon.PumpPluginAbstract;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpDriverState; import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpDriverState;
@ -49,6 +57,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfileEntry; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfileEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCustomActionType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicStatusRefreshType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicStatusRefreshType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus; import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
@ -76,10 +85,16 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private boolean firstRun = true; private boolean firstRun = true;
private boolean isRefresh = false; private boolean isRefresh = false;
private boolean isBasalProfileInvalid = false; private boolean isBasalProfileInvalid = false;
private boolean basalProfileChanged = false;
private Map<MedtronicStatusRefreshType, Long> statusRefreshMap = new HashMap<>(); private Map<MedtronicStatusRefreshType, Long> statusRefreshMap = new HashMap<>();
private boolean isInitialized = false; private boolean isInitialized = false;
private MedtronicHistoryData medtronicHistoryData; private MedtronicHistoryData medtronicHistoryData;
private MedtronicCommunicationManager medtronicCommunicationManager; private MedtronicCommunicationManager medtronicCommunicationManager;
private PumpHistoryEntry lastPumpHistoryEntry;
public static Gson gsonInstance = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
public static Gson gsonInstancePretty = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting().create();
private MedtronicPumpPlugin() { private MedtronicPumpPlugin() {
@ -94,7 +109,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
); );
// TODO remove this later // TODO remove this later
displayConnectionMessages = true; displayConnectionMessages = false;
medtronicHistoryData = new MedtronicHistoryData(); medtronicHistoryData = new MedtronicHistoryData();
// medtronicCommunicationManager = MedtronicCommunicationManager.getInstance(); // medtronicCommunicationManager = MedtronicCommunicationManager.getInstance();
@ -159,24 +174,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
this.pumpStatus = pumpStatusLocal; this.pumpStatus = pumpStatusLocal;
// this is only thing that can change, by being configured
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; // WIP
pumpDescription.isTempBasalCapable = true; // WIP
pumpDescription.isExtendedBolusCapable = false;
pumpDescription.isSetBasalProfileCapable = true;
// unchangable
pumpDescription.tempBasalStyle = PumpDescription.PERCENT;
pumpDescription.tempDurationStep15mAllowed = false;
pumpDescription.tempDurationStep30mAllowed = true;
pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = false;
pumpDescription.is30minBasalRatesCapable = true;
pumpDescription.supportsTDDs = true;
pumpDescription.needsManualTDDLoad = false;
// set first Medtronic Pump Start // set first Medtronic Pump Start
if (!SP.contains(MedtronicConst.Statistics.FirstPumpStart)) { if (!SP.contains(MedtronicConst.Statistics.FirstPumpStart)) {
SP.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis()); SP.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis());
@ -194,7 +194,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
SystemClock.sleep(60000); SystemClock.sleep(60000);
if (doWeHaveAnyStatusNeededRefereshing()) { if (doWeHaveAnyStatusNeededRefereshing()) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Manual Status Refresh", null); ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Scheduled Status Refresh", null);
} }
} while (serviceRunning); } while (serviceRunning);
@ -235,13 +235,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
} }
@Override // @Override
public boolean isSuspended() { // public boolean isSuspended() {
// TODO remove // // TO DO remove
LOG.debug("MedtronicPumpPlugin::isSuspended"); // LOG.debug("MedtronicPumpPlugin::isSuspended");
return isServiceSet() && medtronicHistoryData.isSuspended(); // return isServiceSet() && medtronicHistoryData.is();
} // }
@Override @Override
public boolean isBusy() { public boolean isBusy() {
@ -316,15 +315,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable); MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
return; return;
// new PumpEnactResult() //
// .success(false) //
// .enacted(false) //
// .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
} }
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
Set<MedtronicStatusRefreshType> refreshTypesNeededToReschedule = new HashSet<>();
// execute
for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefreshMap.entrySet()) { for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefreshMap.entrySet()) {
if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) { if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) {
@ -339,7 +336,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
case BatteryStatus: case BatteryStatus:
case RemainingInsulin: { case RemainingInsulin: {
medtronicUIComm.executeCommand(refreshType.getKey().getCommandType()); medtronicUIComm.executeCommand(refreshType.getKey().getCommandType());
scheduleNextRefresh(refreshType.getKey()); refreshTypesNeededToReschedule.add(refreshType.getKey());
resetTime = true; resetTime = true;
} }
break; break;
@ -347,14 +344,17 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
case Configuration: { case Configuration: {
medtronicUIComm.executeCommand(refreshType.getKey().getCommandType()); medtronicUIComm.executeCommand(refreshType.getKey().getCommandType());
resetTime = true; resetTime = true;
medtronicHistoryData.resetRelevantConfigurationChanged();
} }
break; break;
} }
} }
} }
// reschedule
for (MedtronicStatusRefreshType refreshType : refreshTypesNeededToReschedule) {
scheduleNextRefresh(refreshType);
}
if (resetTime) if (resetTime)
pumpStatusLocal.setLastCommunicationToNow(); pumpStatusLocal.setLastCommunicationToNow();
@ -381,7 +381,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private void initializePump(boolean realInit) { private void initializePump(boolean realInit) {
LOG.error("initializePump - start"); LOG.info(getLogPrefix() + "initializePump - start");
if (medtronicCommunicationManager == null) { if (medtronicCommunicationManager == null) {
medtronicCommunicationManager = MedtronicCommunicationManager.getInstance(); medtronicCommunicationManager = MedtronicCommunicationManager.getInstance();
@ -394,7 +394,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (isRefresh) { if (isRefresh) {
if (isPumpNotReachable()) { if (isPumpNotReachable()) {
LOG.error("initializePump::Pump unreachable."); LOG.error(getLogPrefix() + "initializePump::Pump unreachable.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable); MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
setRefreshButtonEnabled(true); setRefreshButtonEnabled(true);
@ -410,13 +410,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel); medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel);
} else { } else {
if (pumpStatusLocal.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) { if (pumpStatusLocal.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) {
LOG.warn("Configured pump is not the same as one detected."); LOG.warn(getLogPrefix() + "Configured pump is not the same as one detected.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame); MedtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame);
} }
} }
// TODO this call might need to do deeper call (several pages) this.pumpState = PumpDriverState.Connected;
// pump history handling - special, updates every 5 minutes ???
readPumpHistory(); readPumpHistory();
// TODO rewrite reading of data to be done in background or different thread perhaps ?? // TODO rewrite reading of data to be done in background or different thread perhaps ??
@ -430,7 +430,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20); scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20);
// configuration (once and then if history shows config changes) // configuration (once and then if history shows config changes)
medtronicUIComm.executeCommand(MedtronicCommandType.getSettings(MedtronicUtil.getMedtronicPumpModel())); // medtronicUIComm.executeCommand(MedtronicCommandType.getSettings(MedtronicUtil.getMedtronicPumpModel()));
// time (1h) // time (1h)
medtronicUIComm.executeCommand(MedtronicCommandType.RealTimeClock); medtronicUIComm.executeCommand(MedtronicCommandType.RealTimeClock);
@ -444,8 +444,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (errorCount >= 5) { if (errorCount >= 5) {
LOG.error("Number of error counts was 5 or more. Starting tunning."); LOG.error("Number of error counts was 5 or more. Starting tunning.");
setRefreshButtonEnabled(true);
ServiceTaskExecutor.startTask(new WakeAndTuneTask()); ServiceTaskExecutor.startTask(new WakeAndTuneTask());
setRefreshButtonEnabled(true); // FIXME
return; return;
} }
@ -462,6 +462,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
.putCustomAttribute("version", BuildConfig.VERSION)); .putCustomAttribute("version", BuildConfig.VERSION));
isInitialized = true; isInitialized = true;
// this.pumpState = PumpDriverState.Initialized;
this.firstRun = false; this.firstRun = false;
} }
@ -474,7 +475,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
return true; return true;
} }
if (!medtronicHistoryData.hasBasalProfileChanged() && getMDTPumpStatus().basalsByHour != null) { if (!basalProfileChanged && getMDTPumpStatus().basalsByHour != null) {
return (!isBasalProfileInvalid); return (!isBasalProfileInvalid);
} }
@ -484,11 +485,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable); MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
setRefreshButtonEnabled(true); setRefreshButtonEnabled(true);
return false; return true; // we don't won't setting profile if pump unreachable
// new PumpEnactResult() //
// .success(false) //
// .enacted(false) //
// .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
} }
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
@ -506,7 +503,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
int index = 0; int index = 0;
if (basalsByHour == null) if (basalsByHour == null)
return true; return true; // we don't want to set profile again, unless we are sure
for (Profile.BasalValue basalValue : profile.getBasalValues()) { for (Profile.BasalValue basalValue : profile.getBasalValues()) {
@ -527,6 +524,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (!invalid) { if (!invalid) {
LOG.debug("Basal profile is same as AAPS one."); LOG.debug("Basal profile is same as AAPS one.");
basalProfileChanged = false;
} else { } else {
LOG.debug("Basal profile on Pump is different than the AAPS one."); LOG.debug("Basal profile on Pump is different than the AAPS one.");
} }
@ -538,9 +536,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
isBasalProfileInvalid = invalid; isBasalProfileInvalid = invalid;
if (!invalid)
medtronicHistoryData.resetBasalProfileChanged();
setRefreshButtonEnabled(true); setRefreshButtonEnabled(true);
return (!invalid); return (!invalid);
@ -774,18 +769,18 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
getMDTPumpStatus(); getMDTPumpStatus();
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes); LOG.info(getLogPrefix() + "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes);
// read current TBR // read current TBR
TempBasalPair tbrCurrent = readTBR(); TempBasalPair tbrCurrent = readTBR();
if (tbrCurrent == null) { if (tbrCurrent == null) {
LOG.warn("MedtronicPumpPlugin::setTempBasalAbsolute - Could not read current TBR, canceling operation."); LOG.warn(getLogPrefix() + "setTempBasalAbsolute - Could not read current TBR, canceling operation.");
setRefreshButtonEnabled(true); finishAction("TBR");
return new PumpEnactResult().success(false).enacted(false) return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr)); .comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr));
} else { } else {
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute: Current Basal: duration: {} min, rate={}", LOG.info(getLogPrefix() + "setTempBasalAbsolute: Current Basal: duration: {} min, rate={}",
tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate()); tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate());
} }
@ -800,8 +795,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
} }
if (sameRate) { if (sameRate) {
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - No enforceNew and same rate. Exiting."); LOG.info(getLogPrefix() + "setTempBasalAbsolute - No enforceNew and same rate. Exiting.");
setRefreshButtonEnabled(true); finishAction("TBR");
return new PumpEnactResult().success(true).enacted(false); return new PumpEnactResult().success(true).enacted(false);
} }
} }
@ -810,7 +805,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// if TBR is running we will cancel it. // if TBR is running we will cancel it.
if (tbrCurrent.getInsulinRate() != 0.0f && tbrCurrent.getDurationMinutes() > 0) { if (tbrCurrent.getInsulinRate() != 0.0f && tbrCurrent.getDurationMinutes() > 0) {
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - TBR running - so canceling it."); LOG.info(getLogPrefix() + "setTempBasalAbsolute - TBR running - so canceling it.");
// CANCEL // CANCEL
@ -819,11 +814,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask2.returnData; Boolean response = (Boolean)responseTask2.returnData;
if (response) { if (response) {
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - Current TBR cancelled."); LOG.info(getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled.");
} else { } else {
LOG.error("MedtronicPumpPlugin::setTempBasalAbsolute - Cancel TBR failed."); LOG.error(getLogPrefix() + "setTempBasalAbsolute - Cancel TBR failed.");
setRefreshButtonEnabled(true); finishAction("TBR");
return new PumpEnactResult().success(false).enacted(false) return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr)); .comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr));
@ -836,7 +831,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask.returnData; Boolean response = (Boolean)responseTask.returnData;
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - setTBR. Response: " + response); LOG.info(getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response);
if (response) { if (response) {
// FIXME put this into UIPostProcessor // FIXME put this into UIPostProcessor
@ -855,22 +850,30 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
incrementStatistics(MedtronicConst.Statistics.TBRsSet); incrementStatistics(MedtronicConst.Statistics.TBRsSet);
} }
MainApp.bus().post(new EventRefreshOverview("TBR")); finishAction("TBR");
triggerUIChange();
setRefreshButtonEnabled(true); setRefreshButtonEnabled(true);
return new PumpEnactResult().success(response).enacted(response); return new PumpEnactResult().success(response).enacted(response);
} }
// Gson gson = new Gson();
PumpHistoryEntry lastPumpHistoryEntry; private void finishAction(String overviewKey) {
if (overviewKey != null)
MainApp.bus().post(new EventRefreshOverview(overviewKey));
triggerUIChange();
setRefreshButtonEnabled(true);
}
private void readPumpHistory() { private void readPumpHistory() {
LOG.error("MedtronicPumpPlugin::readPumpHistory NOT IMPLEMENTED.");
// readPumpHistoryLogic(); LOG.error(getLogPrefix() + "readPumpHistory WIP.");
readPumpHistoryLogic();
scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory); scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory);
@ -878,7 +881,70 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1); scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1);
} }
// FIXME set last read if (medtronicHistoryData.hasPumpTimeChanged()) {
scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1);
}
if (medtronicHistoryData.hasBasalProfileChanged()) {
this.basalProfileChanged = true;
}
PumpDriverState previousState = this.pumpState;
if (medtronicHistoryData.isPumpSuspended(this.pumpState == PumpDriverState.Suspended)) {
scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1);
this.pumpState = PumpDriverState.Suspended;
LOG.debug(getLogPrefix() + "isPumpSuspended: true");
} else {
if (previousState == PumpDriverState.Suspended) {
this.pumpState = PumpDriverState.Ready;
}
LOG.debug(getLogPrefix() + "isPumpSuspended: false");
}
List<PumpHistoryEntry> tdds = medtronicHistoryData.getTDDs();
if (tdds.size() > 0) {
processTDDs(tdds);
}
List<PumpHistoryEntry> tdds2 = medtronicHistoryData.getTDDs2();
LOG.debug("TDDs2: {}", gsonInstancePretty.toJson(tdds2));
List<PumpHistoryEntry> treatments = medtronicHistoryData.getTreatments();
if (treatments.size() > 0) {
processTreatments(treatments);
}
this.medtronicHistoryData.finalizeNewHistoryRecords();
}
private void processTreatments(List<PumpHistoryEntry> treatments) {
// FIXME bolus and tbr
LOG.error(getLogPrefix() + "Treatments found: {}. Not processed.\n", treatments.size());
MedtronicHistoryData.showLogs(null, gsonInstancePretty.toJson(treatments));
}
private void processTDDs(List<PumpHistoryEntry> tdds) {
LOG.error(getLogPrefix() + "TDDs found: {}. Not processed.\n{}", tdds.size(), gsonInstancePretty.toJson(tdds));
// FIXME tdd
List<TDD> tdDsForLastXDays = MainApp.getDbHelper().getTDDs();
for (TDD tdDsForLastXDay : tdDsForLastXDays) {
LOG.debug("TDD: " + tdDsForLastXDay);
}
} }
@ -886,23 +952,26 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
LocalDateTime targetDate = null; LocalDateTime targetDate = null;
// TODO read History
// if (lastPumpHistoryEntry == null) {
// lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, null);
// }
if (lastPumpHistoryEntry == null) { if (lastPumpHistoryEntry == null) {
Long lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, null); LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: null");
Long lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, 0L);
LocalDateTime timeMinus36h = new LocalDateTime(); LocalDateTime timeMinus36h = new LocalDateTime();
timeMinus36h = timeMinus36h.minusHours(36); timeMinus36h = timeMinus36h.minusHours(36);
medtronicHistoryData.setIsInInit(true);
if (lastPumpHistoryEntryTime == null) { if (lastPumpHistoryEntryTime == 0L) {
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: 0L - targetDate: "
+ targetDate);
targetDate = timeMinus36h; targetDate = timeMinus36h;
} else { } else {
LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime);
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: {} - targetDate: {}",
lastHistoryRecordTime, targetDate);
medtronicHistoryData.setLastHistoryRecordTime(DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime)); medtronicHistoryData.setLastHistoryRecordTime(DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime));
lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12); // we get last 12 hours of history to lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12); // we get last 12 hours of history to
@ -914,15 +983,25 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
} }
targetDate = (timeMinus36h.isAfter(lastHistoryRecordTime) ? timeMinus36h : lastHistoryRecordTime); targetDate = (timeMinus36h.isAfter(lastHistoryRecordTime) ? timeMinus36h : lastHistoryRecordTime);
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): targetDate: " + targetDate);
} }
} else {
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - {}",
gsonInstancePretty.toJson(lastPumpHistoryEntry));
medtronicHistoryData.setIsInInit(false);
medtronicHistoryData.setLastHistoryRecordTime(null);
} }
// FIXME read history MedtronicUITask responseTask2 = medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData,
lastPumpHistoryEntry, targetDate);
PumpHistoryResult historyResult = new PumpHistoryResult(null, null); PumpHistoryResult historyResult = (PumpHistoryResult)responseTask2.returnData;
PumpHistoryEntry latestEntry = historyResult.getLatestEntry(); PumpHistoryEntry latestEntry = historyResult.getLatestEntry();
LOG.debug(getLogPrefix() + "Last entry: " + latestEntry);
if (latestEntry == null) // no new history to read if (latestEntry == null) // no new history to read
return; return;
@ -930,6 +1009,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
SP.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, SP.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry,
DateTimeUtil.toATechDate(latestEntry.getLocalDateTime())); DateTimeUtil.toATechDate(latestEntry.getLocalDateTime()));
this.medtronicHistoryData.addNewHistory(historyResult);
this.medtronicHistoryData.filterNewEntries();
// determine if first run, if yes detrmine how much of update do we need // determine if first run, if yes detrmine how much of update do we need
// first run: // first run:
// get last hiostory entry, if not there download 1.5 days of data // get last hiostory entry, if not there download 1.5 days of data
@ -963,7 +1045,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
case RemainingInsulin: { case RemainingInsulin: {
Double remaining = pumpStatusLocal.reservoirRemainingUnits; Double remaining = pumpStatusLocal.reservoirRemainingUnits;
int min = 0; int min;
if (remaining > 50) if (remaining > 50)
min = 4 * 60; min = 4 * 60;
else if (remaining > 20) else if (remaining > 20)
@ -975,6 +1057,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
} }
break; break;
case PumpTime:
case Configuration: case Configuration:
case PumpHistory: { case PumpHistory: {
statusRefreshMap.put(refreshType, getTimeInFutureFromMinutes(refreshType.getRefreshTime() statusRefreshMap.put(refreshType, getTimeInFutureFromMinutes(refreshType.getRefreshTime()
@ -1016,7 +1099,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override @Override
public PumpEnactResult cancelTempBasal(boolean enforceNew) { public PumpEnactResult cancelTempBasal(boolean enforceNew) {
LOG.info("MedtronicPumpPlugin::cancelTempBasal - started"); LOG.info(getLogPrefix() + "cancelTempBasal - started");
if (isPumpNotReachable()) { if (isPumpNotReachable()) {
@ -1035,13 +1118,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (tbrCurrent != null) { if (tbrCurrent != null) {
if (tbrCurrent.getInsulinRate() == 0.0f && tbrCurrent.getDurationMinutes() == 0) { if (tbrCurrent.getInsulinRate() == 0.0f && tbrCurrent.getDurationMinutes() == 0) {
LOG.info("MedtronicPumpPlugin::cancelTempBasal - TBR already canceled."); LOG.info(getLogPrefix() + "cancelTempBasal - TBR already canceled.");
setRefreshButtonEnabled(true); finishAction("TBR");
return new PumpEnactResult().success(true).enacted(false); return new PumpEnactResult().success(true).enacted(false);
} }
} else { } else {
LOG.warn("MedtronicPumpPlugin::cancelTempBasal - Could not read currect TBR, canceling operation."); LOG.warn(getLogPrefix() + "cancelTempBasal - Could not read currect TBR, canceling operation.");
setRefreshButtonEnabled(true); finishAction("TBR");
return new PumpEnactResult().success(false).enacted(false) return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr)); .comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr));
} }
@ -1051,13 +1134,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask2.returnData; Boolean response = (Boolean)responseTask2.returnData;
if (response) { if (response) {
LOG.info("MedtronicPumpPlugin::cancelTempBasal - Cancel TBR successful."); LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR successful.");
} else { } else {
LOG.info("MedtronicPumpPlugin::cancelTempBasal - Cancel TBR failed."); LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR failed.");
} }
setRefreshButtonEnabled(true); finishAction("TBR");
return new PumpEnactResult().success(response).enacted(response); return new PumpEnactResult().success(response).enacted(response);
} }
@ -1109,12 +1192,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
MedtronicPumpStatus pumpStatus = getMDTPumpStatus(); MedtronicPumpStatus pumpStatus = getMDTPumpStatus();
if (pumpStatusLocal.maxBasal == null) if (pumpStatus.maxBasal == null)
return null; return null;
for (BasalProfileEntry profileEntry : basalProfile.getEntries()) { for (BasalProfileEntry profileEntry : basalProfile.getEntries()) {
if (profileEntry.rate > pumpStatusLocal.maxBasal) { if (profileEntry.rate > pumpStatus.maxBasal) {
stringBuilder.append(profileEntry.startTime.toString("HH:mm") + "=" + profileEntry.rate); stringBuilder.append(profileEntry.startTime.toString("HH:mm") + "=" + profileEntry.rate);
@ -1176,40 +1259,72 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
} }
// we don't loadTDD. TDD is read from Pump History // // we don't loadTDD. TDD is read from Pump History
@Override // @Override
public PumpEnactResult loadTDDs() { // public PumpEnactResult loadTDDs() {
return OPERATION_NOT_SUPPORTED; // return OPERATION_NOT_SUPPORTED;
} // }
// public void connect(String reason) {
// // we don't use this.
// // we connect to RileyLink on startup and keep connection opened, then connection to pump
// // is established when needed.
//
// // TODO remove
// LOG.debug("MedtronicPumpPlugin::connect (reason: {})", reason);
// }
public void connect(String reason) { // public void disconnect(String reason) {
// we don't use this. // // see comment in connect
// we connect to RileyLink on startup and keep connection opened, then connection to pump // // TO DO remove
// is established when needed. // LOG.debug("MedtronicPumpPlugin::disconnect (reason: {})", reason);
// }
// 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");
}
// public void stopConnecting() {
// // see comment in connect
// // TO DO remove
// LOG.debug("MedtronicPumpPlugin::stopConnecting");
// }
@Override @Override
public void stopBolusDelivering() { public void stopBolusDelivering() {
// Medtronic doesn't have Bolus cancel, so we fake it. // Medtronic doesn't have Bolus cancel, so we fake it.
} }
List<CustomAction> customActions = null;
@Override
public List<CustomAction> getCustomActions() {
if (customActions == null) {
this.customActions = new ArrayList<>();
CustomAction ca = new CustomAction(R.string.medtronic_custom_action_wake_and_tune,
MedtronicCustomActionType.WakeUpAndTune);
this.customActions.add(ca);
}
return this.customActions;
}
@Override
public PumpEnactResult executeCustomAction(CustomActionType customActionType) {
MedtronicCustomActionType mcat = (MedtronicCustomActionType)customActionType;
switch (mcat) {
case WakeUpAndTune:
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
break;
default:
break;
}
return null;
}
} }

View file

@ -1,15 +1,14 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm; package info.nightscout.androidaps.plugins.PumpMedtronic.comm;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.joda.time.Instant;
import org.joda.time.LocalDateTime; import org.joda.time.LocalDateTime;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import android.content.Context; 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.RileyLinkCommunicationManager;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
@ -19,11 +18,11 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMes
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioPacket; 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.data.RadioResponse;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessageType; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessageType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.Page; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.Page;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history_old.Record;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.RawHistoryPage; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.RawHistoryPage;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
@ -65,15 +64,17 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
private MedtronicPumpHistoryDecoder pumpHistoryDecoder; private MedtronicPumpHistoryDecoder pumpHistoryDecoder;
private boolean doWakeUpBeforeCommand = true; private boolean doWakeUpBeforeCommand = true;
private boolean firstConnection = true; private boolean firstConnection = true;
private boolean medtronicHistoryTesting = false; // TODO remove when not needed
public MedtronicCommunicationManager(Context context, RFSpy rfspy, RileyLinkTargetFrequency targetFrequency) { public MedtronicCommunicationManager(Context context, RFSpy rfspy) {
super(context, rfspy, targetFrequency); super(context, rfspy);
medtronicCommunicationManager = this; medtronicCommunicationManager = this;
this.medtronicConverter = new MedtronicConverter(); this.medtronicConverter = new MedtronicConverter();
this.pumpHistoryDecoder = new MedtronicPumpHistoryDecoder(); this.pumpHistoryDecoder = new MedtronicPumpHistoryDecoder();
MedtronicUtil.getPumpStatus().previousConnection = SP.getLong( MedtronicUtil.getPumpStatus().previousConnection = SP.getLong(
RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L);
} }
@ -100,13 +101,18 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
} }
public boolean isDeviceReachable() {
return isDeviceReachable(false);
}
/** /**
* We do actual wakeUp and compare PumpModel with currently selected one. If returned model is not Unknown, * We do actual wakeUp and compare PumpModel with currently selected one. If returned model is not Unknown,
* pump is reachable. * pump is reachable.
* *
* @return * @return
*/ */
public boolean isDeviceReachable() { public boolean isDeviceReachable(boolean canPreventTuneUp) {
PumpDeviceState state = MedtronicUtil.getPumpDeviceState(); PumpDeviceState state = MedtronicUtil.getPumpDeviceState();
@ -135,8 +141,6 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
rfSpyResponse.wasTimeout()); rfSpyResponse.wasTimeout());
} else { } else {
// rememberLastGoodDeviceCommunicationTime();
// radioResponse.rssi; // radioResponse.rssi;
Object dataResponse = medtronicConverter.convertResponse(MedtronicCommandType.PumpModel, Object dataResponse = medtronicConverter.convertResponse(MedtronicCommandType.PumpModel,
pumpResponse.getRawContent()); pumpResponse.getRawContent());
@ -175,11 +179,16 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.warn("isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw())); LOG.warn("isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
} }
SystemClock.sleep(1000);
} }
if (state != PumpDeviceState.PumpUnreachable) if (state != PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable); MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable);
if (!canPreventTuneUp)
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
return false; return false;
} }
@ -188,7 +197,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
@Override @Override
public boolean tryToConnectToDevice() { public boolean tryToConnectToDevice() {
return isDeviceReachable(); return isDeviceReachable(true);
// wakeUp(true); // wakeUp(true);
// //
@ -378,6 +387,10 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
if (doWakeUpBeforeCommand) if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false); wakeUp(receiverDeviceAwakeForMinutes, false);
LOG.debug("Current command: " + MedtronicUtil.getCurrentCommand());
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active);
for (int pageNumber = 0; pageNumber < 16; pageNumber++) { for (int pageNumber = 0; pageNumber < 16; pageNumber++) {
RawHistoryPage rawHistoryPage = new RawHistoryPage(); RawHistoryPage rawHistoryPage = new RawHistoryPage();
@ -454,6 +467,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.error("getPumpHistory: checksum is wrong"); LOG.error("getPumpHistory: checksum is wrong");
} }
// TODO handle error states
rawHistoryPage.dumpToDebug(); rawHistoryPage.dumpToDebug();
List<PumpHistoryEntry> medtronicHistoryEntries = pumpHistoryDecoder.processPageAndCreateRecords( List<PumpHistoryEntry> medtronicHistoryEntries = pumpHistoryDecoder.processPageAndCreateRecords(
@ -467,11 +482,15 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.debug("getPumpHistory: Search status: Search finished: {}", pumpTotalResult.isSearchFinished()); LOG.debug("getPumpHistory: Search status: Search finished: {}", pumpTotalResult.isSearchFinished());
if (pumpTotalResult.isSearchFinished()) { if (pumpTotalResult.isSearchFinished()) {
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return pumpTotalResult; return pumpTotalResult;
} }
} }
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return pumpTotalResult; return pumpTotalResult;
} }
@ -558,31 +577,29 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
} }
public ArrayList<Page> getAllHistoryPages() { // public ArrayList<Page> getAllHistoryPages() {
ArrayList<Page> pages = new ArrayList<>(); // ArrayList<Page> pages = new ArrayList<>();
//
for (int pageNum = 0; pageNum < 16; pageNum++) { // for (int pageNum = 0; pageNum < 16; pageNum++) {
pages.add(getPumpHistoryPage(pageNum)); // pages.add(getPumpHistoryPage(pageNum));
} // }
//
return pages; // return pages;
} // }
public ArrayList<Page> getHistoryEventsSinceDate(Instant when) {
ArrayList<Page> pages = new ArrayList<>();
for (int pageNum = 0; pageNum < 16; pageNum++) {
pages.add(getPumpHistoryPage(pageNum));
for (Page page : pages) {
for (Record r : page.mRecordList) {
LocalDateTime timestamp = r.getTimestamp().getLocalDateTime();
LOG.info("Found record: (" + r.getClass().getSimpleName() + ") " + timestamp.toString());
}
}
}
return pages;
}
// public ArrayList<Page> getHistoryEventsSinceDate(Instant when) {
// ArrayList<Page> pages = new ArrayList<>();
// for (int pageNum = 0; pageNum < 16; pageNum++) {
// pages.add(getPumpHistoryPage(pageNum));
// for (Page page : pages) {
// for (Record r : page.mRecordList) {
// LocalDateTime timestamp = r.getTimestamp().getLocalDateTime();
// LOG.info("Found record: (" + r.getClass().getSimpleName() + ") " + timestamp.toString());
// }
// }
// }
// return pages;
// }
public String getErrorResponse() { public String getErrorResponse() {
return this.errorMessage; return this.errorMessage;

View file

@ -5,7 +5,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.joda.time.LocalDateTime; import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.PumpCommon.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
@ -34,6 +39,8 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte
protected List<Byte> rawData; protected List<Byte> rawData;
protected static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm:ss");
protected int[] sizes = new int[3]; protected int[] sizes = new int[3];
protected byte[] head; protected byte[] head;
@ -41,8 +48,14 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte
protected byte[] body; protected byte[] body;
protected LocalDateTime dateTime; protected LocalDateTime dateTime;
// protected PumpTimeStampedRecord historyEntryDetails;
@Expose
public String DT;
@Expose
public long atechDateTime;
@Expose
protected Map<String, Object> decodedData; protected Map<String, Object> decodedData;
@ -231,6 +244,13 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte
public void setLocalDateTime(LocalDateTime atdate) { public void setLocalDateTime(LocalDateTime atdate) {
this.dateTime = atdate; this.dateTime = atdate;
// this.DT = atdate.toString(dateTimeFormatter);
}
public void setAtechDateTime(long dt) {
this.atechDateTime = dt;
this.DT = DateTimeUtil.toString(this.atechDateTime);
} }

View file

@ -5,8 +5,6 @@ import java.util.Arrays;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import android.util.Log;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC; import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
@ -16,9 +14,9 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
*/ */
public class RawHistoryPage { public class RawHistoryPage {
private static final String TAG = "RawHistoryPage";
private static final Logger LOG = LoggerFactory.getLogger(RawHistoryPage.class); private static final Logger LOG = LoggerFactory.getLogger(RawHistoryPage.class);
byte[] data = new byte[0];
private byte[] data = new byte[0];
public RawHistoryPage() { public RawHistoryPage() {
@ -69,14 +67,21 @@ public class RawHistoryPage {
public void dumpToDebug() { public void dumpToDebug() {
int linesize = 80; int linesize = 80;
int offset = 0; int offset = 0;
StringBuffer sb = new StringBuffer();
while (offset < data.length) { while (offset < data.length) {
int bytesToLog = linesize; int bytesToLog = linesize;
if (offset + linesize > data.length) { if (offset + linesize > data.length) {
bytesToLog = data.length - offset; bytesToLog = data.length - offset;
} }
Log.d(TAG, ByteUtil.shortHexString(ByteUtil.substring(data, offset, bytesToLog))); sb.append(ByteUtil.shortHexString(ByteUtil.substring(data, offset, bytesToLog)) + " ");
// sb.append("\n");
offset += linesize; offset += linesize;
} }
LOG.debug("History Page Data:\n{}", sb.toString());
} }
} }

View file

@ -110,12 +110,6 @@ public class MedtronicCGMSHistoryDecoder extends MedtronicHistoryDecoder {
} }
// @Override
// public List<? extends MedtronicHistoryEntry> processPageAndCreateRecords(RawHistoryPage page) throws Exception {
// List<Byte> dataClear = checkPage(page, false);
// return createRecords(dataClear);
// }
protected <E extends MedtronicHistoryEntry> List<E> createRecords(List<Byte> dataClearInput, Class<E> clazz) { protected <E extends MedtronicHistoryEntry> List<E> createRecords(List<Byte> dataClearInput, Class<E> clazz) {
// List<MinimedHistoryEntry> listRecords = new // List<MinimedHistoryEntry> listRecords = new
// ArrayList<MinimedHistoryEntry>(); // ArrayList<MinimedHistoryEntry>();

View file

@ -9,16 +9,17 @@ import org.joda.time.LocalDateTime;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import android.util.Log;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.MedtronicHistoryDecoder; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.MedtronicHistoryDecoder;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.MedtronicHistoryEntry; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.MedtronicHistoryEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.RecordDecodeStatus; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.RecordDecodeStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusDTO; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusWizardDTO; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusWizardDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.DailyTotalsDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType;
@ -48,7 +49,6 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder { public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpHistoryDecoder.class); private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpHistoryDecoder.class);
private static final String TAG = "MdtPump";
// PumpValuesWriter pumpValuesWriter = null; // PumpValuesWriter pumpValuesWriter = null;
@ -61,22 +61,10 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
public MedtronicPumpHistoryDecoder() { public MedtronicPumpHistoryDecoder() {
super();
} }
// public List<? extends MedtronicHistoryEntry> processPageAndCreateRecords(RawHistoryPage page) { protected <E extends MedtronicHistoryEntry> List<E> createRecords(List<Byte> dataClear, Class<E> clazz) {
// List<Byte> dataClear = checkPage(page, false);
// return createRecords(dataClear);
// }
// public <E extends MedtronicHistoryEntry> List<E> processPageAndCreateRecords(RawHistoryPage rawHistoryPage,
// boolean partial, Class<E> clazz) {
//
// return null;
// }
public <E extends MedtronicHistoryEntry> List<E> createRecords(List<Byte> dataClear, Class<E> clazz) {
prepareStatistics(); prepareStatistics();
int counter = 0; int counter = 0;
@ -89,8 +77,8 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
int elementStart = 0; int elementStart = 0;
if (dataClear.size() == 0) { if (dataClear.size() == 0) {
Log.e(TAG, "Empty page."); LOG.error("Empty page.");
// return; return outList;
} }
do { do {
@ -107,7 +95,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
continue; continue;
} else { } else {
if (skipped != null) { if (skipped != null) {
Log.v(TAG, " ... Skipped " + skipped); LOG.debug(" ... Skipped " + skipped);
skipped = null; skipped = null;
} }
} }
@ -148,7 +136,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
listRawData.add(dataClear.get(counter)); listRawData.add(dataClear.get(counter));
counter++; counter++;
} catch (Exception ex) { } catch (Exception ex) {
Log.e(TAG, "OpCode: " + HexDump.getCorrectHexValue((byte)opCode) + ", Invalid package: " LOG.error("OpCode: " + HexDump.getCorrectHexValue((byte)opCode) + ", Invalid package: "
+ HexDump.toHexStringDisplayable(listRawData)); + HexDump.toHexStringDisplayable(listRawData));
// throw ex; // throw ex;
incompletePacket = true; incompletePacket = true;
@ -189,38 +177,16 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
RecordDecodeStatus decoded = decodeRecord(pe); RecordDecodeStatus decoded = decodeRecord(pe);
// if (pe.getEntryType() == if (decoded == RecordDecodeStatus.WIP) {
// PumpHistoryEntryType.UnknownBasePacket)
// {
// decoded = RecordDecodeStatus.Unknown;
// }
// else
// {
// decoded = decodeRecord(pe);
// }
// System.out.println("Found entry: " + entryType.name() +
// " ["
// + bitUtils.getDebugByteListHex(listRawData) + "] ");
// FIXME
// if (!decoded)
// System.out.println("#" + record + " " + pe);
// if (decoded)
// LOG.info("#" + record + " " + pe);
// else
// LOG.warn("#" + record + " BAD: " + pe);
if ((decoded == RecordDecodeStatus.OK) || (decoded == RecordDecodeStatus.Ignored)) {
LOG.info("#" + record + " " + decoded.getDescription() + " " + pe);
Log.i(TAG, "#" + record + " " + decoded.getDescription() + " -- " + pe);
} else {
LOG.warn("#" + record + " " + decoded.getDescription() + " " + pe); LOG.warn("#" + record + " " + decoded.getDescription() + " " + pe);
Log.w(TAG, "#" + record + " " + decoded.getDescription() + " -- " + pe);
} }
// if ((decoded == RecordDecodeStatus.OK) || (decoded == RecordDecodeStatus.Ignored)) {
// LOG.info("#" + record + " " + decoded.getDescription() + " " + pe);
// } else {
// LOG.warn("#" + record + " " + decoded.getDescription() + " " + pe);
// }
addToStatistics(pe, decoded, null); addToStatistics(pe, decoded, null);
record++; record++;
@ -231,11 +197,6 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
} }
} }
// System.out.println("Counter: " + counter);
// if (counter > 100)
// break;
} while (counter < dataClear.size()); } while (counter < dataClear.size());
return outList; return outList;
@ -276,31 +237,39 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
} }
// LOG.debug("decodeRecord: type={}", entry.getEntryType()); // LOG.debug("decodeRecord: type={}", entry.getEntryType());
decodeDateTime(entry); // decodeDateTime(entry);
switch (entry.getEntryType()) { switch (entry.getEntryType()) {
// not implemented // not implemented
case ChangeBasalProfile_NewProfile:
case ChangeBasalProfile_OldProfile:
case SelectBasalProfile:
case DailyTotals522:
// case IanA8: case DailyTotals522:
case DailyTotals523: case DailyTotals523:
case DailyTotals512: case DailyTotals515:
return RecordDecodeStatus.NotSupported; return decodeDailyTotals(entry); // Not supported at the moment
case SelectBasalProfile:
return RecordDecodeStatus.Ignored; // Not supported at the moment
// WORK IN PROGRESS // WORK IN PROGRESS
// POSSIBLY READY // POSSIBLY READY
case ChangeBasalProfile_OldProfile:
case ChangeBasalProfile_NewProfile:
return decodeBasalProfile(entry);
case BasalProfileStart: case BasalProfileStart:
return decodeBasalProfileStart(entry); return decodeBasalProfileStart(entry);
// AAPS Implementation - Not yet done // AAPS Implementation - Not yet done
// AAPS Implementation - OK entries // AAPS Implementation - OK entries
case ChangeTempBasalType:
case ChangeMaxBolus:
case ChangeMaxBasal:
case ClearSettings:
case SaveSettings:
return RecordDecodeStatus.OK;
// AAPS events (Tbr, Bolus) // AAPS events (Tbr, Bolus)
// AAPS alerts // AAPS alerts
@ -316,14 +285,11 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
case UnabsorbedInsulin: case UnabsorbedInsulin:
case BGReceived: // Ian3F: CGMS case BGReceived: // Ian3F: CGMS
case SensorAlert: // Ian08 CGMS case SensorAlert: // Ian08 CGMS
case ChangeTempBasalType:
case ChangeTimeFormat: case ChangeTimeFormat:
case ChangeReservoirWarningTime: case ChangeReservoirWarningTime:
case ChangeBolusReminderEnable: case ChangeBolusReminderEnable:
case ChangeBolusReminderTime: case ChangeBolusReminderTime:
case ChangeChildBlockEnable: case ChangeChildBlockEnable:
case ChangeMaxBolus:
case ChangeMaxBasal:
case BolusWizardEnabled: case BolusWizardEnabled:
case ChangeBGReminderOffset: case ChangeBGReminderOffset:
case ChangeAlarmClockTime: case ChangeAlarmClockTime:
@ -334,7 +300,6 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
case DeleteBolusReminderTime: case DeleteBolusReminderTime:
case SetAutoOff: case SetAutoOff:
case SelfTest: case SelfTest:
case ClearSettings:
case JournalEntryInsulinMarker: case JournalEntryInsulinMarker:
case JournalEntryOtherMarker: case JournalEntryOtherMarker:
case ChangeBolusWizardSetup: case ChangeBolusWizardSetup:
@ -347,7 +312,6 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
case ChangeSensorRateOfChangeAlertSetup: case ChangeSensorRateOfChangeAlertSetup:
case ChangeBolusScrollStepSize: case ChangeBolusScrollStepSize:
case BolusWizardChange: case BolusWizardChange:
case SaveSettings:
case ChangeVariableBolus: case ChangeVariableBolus:
case ChangeAudioBolus: case ChangeAudioBolus:
case ChangeBGReminderEnable: case ChangeBGReminderEnable:
@ -357,9 +321,9 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
case ChangeCarbUnits: case ChangeCarbUnits:
case ChangeWatchdogEnable: case ChangeWatchdogEnable:
case ChangeOtherDeviceID: case ChangeOtherDeviceID:
case ChangeWatchdogMarriageProfile: // case ChangeWatchdogMarriageProfile:
case DeleteOtherDeviceID: // case DeleteOtherDeviceID:
case ChangeCaptureEventEnable: // case ChangeCaptureEventEnable:
case EventUnknown_MM522_0x45: case EventUnknown_MM522_0x45:
case EventUnknown_MM522_0x46: case EventUnknown_MM522_0x46:
case EventUnknown_MM522_0x47: case EventUnknown_MM522_0x47:
@ -381,6 +345,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
case EventUnknown_MM512_0x94: case EventUnknown_MM512_0x94:
case EventUnknown_MM522_0xE8: case EventUnknown_MM522_0xE8:
case EventUnknown_0x4d: case EventUnknown_0x4d:
case EventUnknown_MM522_0x25:
// LOG.debug(" -- ignored Pump Entry: " + entry.getEntryType().name()); // LOG.debug(" -- ignored Pump Entry: " + entry.getEntryType().name());
return RecordDecodeStatus.Ignored; return RecordDecodeStatus.Ignored;
@ -395,11 +360,11 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
return RecordDecodeStatus.OK; return RecordDecodeStatus.OK;
case TempBasalDuration: case TempBasalDuration:
decodeTempBasal(entry); // decodeTempBasal(entry);
return RecordDecodeStatus.OK; return RecordDecodeStatus.OK;
case TempBasalRate: case TempBasalRate:
decodeTempBasal(entry); // decodeTempBasal(entry);
return RecordDecodeStatus.OK; return RecordDecodeStatus.OK;
case Bolus: case Bolus:
@ -434,8 +399,6 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
// this.writeData(PumpBaseType.Event, PumpEventType.CartridgeRewind, entry.getATechDate()); // this.writeData(PumpBaseType.Event, PumpEventType.CartridgeRewind, entry.getATechDate());
return RecordDecodeStatus.OK; return RecordDecodeStatus.OK;
case EventUnknown_MM522_0x05:
break;
case NoDeliveryAlarm: case NoDeliveryAlarm:
// this.writeData(PumpBaseType.Alarm, PumpAlarms.NoDelivery, entry.getATechDate()); // this.writeData(PumpBaseType.Alarm, PumpAlarms.NoDelivery, entry.getATechDate());
return RecordDecodeStatus.OK; return RecordDecodeStatus.OK;
@ -448,6 +411,12 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
decodePrime(entry); decodePrime(entry);
return RecordDecodeStatus.OK; return RecordDecodeStatus.OK;
case EventUnknown_MM522_0x05:
return RecordDecodeStatus.Ignored;
case TempBasalCombined:
return RecordDecodeStatus.Ignored;
case None: case None:
case UnknownBasePacket: case UnknownBasePacket:
return RecordDecodeStatus.Error; return RecordDecodeStatus.Error;
@ -465,11 +434,68 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
} }
return RecordDecodeStatus.Error; // return RecordDecodeStatus.Error;
} }
private RecordDecodeStatus decodeDailyTotals(PumpHistoryEntry entry) {
entry.addDecodedData("Raw Data", ByteUtil.getHex(entry.getRawData()));
LOG.debug("{} - {}", entry.getEntryType().name(), ByteUtil.getHex(entry.getRawData()));
LOG.debug("{}", entry);
// byte[] data = new byte[] {
// 0x6D, (byte)0xA2, (byte)0x92, 0x05, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x02,
// (byte)0xD4, 0x5B, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x44, 0x64, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00 };
// basal 18.1, bolus 1.7 manual = 1.7
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8, Basal, Bolus, Carbs,
// Bolus=1.7, Fodd, Corr, Manual=1.7,
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
DailyTotalsDTO totals = new DailyTotalsDTO(entry.getEntryType(), entry.getBody());
// System.out.println("Totals:" + totals);
// if (entry.getEntryType() == PumpHistoryEntryType.DailyTotals522) {
//
// // Daily
//
// byte body[] = entry.getBody();
// System.out.println("Totoals 522");
//
// for (int i = 0; i < body.length - 1; i++) {
//
// int j = ByteUtil.toInt(body[i], body[i + 1]);
//
// System.out.println(String.format(
// "index: %d, number=%d, del/40=%.3f, del/10=%.3f, singular=%d, sing_hex=%s", i, j, j / 40.0d,
// j / 10.0d, body[i], ByteUtil.getHex(body[i])));
//
// }
//
// }
return RecordDecodeStatus.WIP;
}
private RecordDecodeStatus decodeBasalProfile(PumpHistoryEntry entry) {
BasalProfile basalProfile = new BasalProfile(entry.getBody());
entry.addDecodedData("Object", basalProfile);
return RecordDecodeStatus.OK;
}
// private void decodeCalBGForPH(PumpHistoryEntry entry) { // private void decodeCalBGForPH(PumpHistoryEntry entry) {
// int high = (entry.getDatetime()[4] & 0x80) >> 7; // int high = (entry.getDatetime()[4] & 0x80) >> 7;
// int bg = bitUtils.toInt(high, getUnsignedInt(entry.getHead()[0])); // int bg = bitUtils.toInt(high, getUnsignedInt(entry.getHead()[0]));
@ -571,7 +597,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
} else { } else {
dto.bloodGlucose = (((body[1] & 0x0F) << 8) | entry.getHead()[0]); dto.bloodGlucose = (((body[1] & 0x0F) << 8) | entry.getHead()[0]);
dto.carbs = (int)body[0]; dto.carbs = (int)body[0];
dto.carbRatio = new Float(body[2]); dto.carbRatio = Float.valueOf(body[2]);
dto.insulinSensitivity = new Float(body[3]); dto.insulinSensitivity = new Float(body[3]);
dto.bgTargetLow = (int)body[4]; dto.bgTargetLow = (int)body[4];
dto.bgTargetHigh = (int)body[12]; dto.bgTargetHigh = (int)body[12];
@ -643,9 +669,9 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
bolus.setInsulinOnBoard(bitUtils.toInt(data[4], data[5]) / 40.0f); bolus.setInsulinOnBoard(bitUtils.toInt(data[4], data[5]) / 40.0f);
bolus.setDuration(data[6] * 30); bolus.setDuration(data[6] * 30);
} else { } else {
bolus.setRequestedAmount(data[0] / 40.0f); bolus.setRequestedAmount(ByteUtil.asUINT8(data[0]) / 40.0f);
bolus.setDeliveredAmount(data[1] / 10.0f); bolus.setDeliveredAmount(ByteUtil.asUINT8(data[1]) / 10.0f);
bolus.setDuration(data[2] * 30); bolus.setDuration(ByteUtil.asUINT8(data[2]) * 30);
} }
bolus.setBolusType((bolus.getDuration() != null && (bolus.getDuration() > 0)) ? PumpBolusType.Extended bolus.setBolusType((bolus.getDuration() != null && (bolus.getDuration() > 0)) ? PumpBolusType.Extended
@ -682,6 +708,14 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
return; return;
} }
decodeTempBasal(this.tbrPreviousRecord, entry);
tbrPreviousRecord = null;
}
public static void decodeTempBasal(PumpHistoryEntry tbrPreviousRecord, PumpHistoryEntry entry) {
PumpHistoryEntry tbrRate = null, tbrDuration = null; PumpHistoryEntry tbrRate = null, tbrDuration = null;
if (entry.getEntryType() == PumpHistoryEntryType.TempBasalRate) { if (entry.getEntryType() == PumpHistoryEntryType.TempBasalRate) {
@ -696,18 +730,6 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
tbrRate = tbrPreviousRecord; tbrRate = tbrPreviousRecord;
} }
// LOG.debug("Rate: " + tbrRate.toString());
// LOG.debug("Durration: " + tbrDuration.toString());
// if ((asUINT8(data[7]) >> 3) == 0) {
// mIsPercent = false;
// tbrRate = (double) (asUINT8(tbrRate.getRawData().get(1)) / 40.0;
// } else {
// mIsPercent = true;
// basalRate = asUINT8(data[1]);
// }
// FIXME
TempBasalPair tbr = new TempBasalPair(tbrRate.getHead()[0], tbrDuration.getHead()[0], (ByteUtil.asUINT8(tbrRate TempBasalPair tbr = new TempBasalPair(tbrRate.getHead()[0], tbrDuration.getHead()[0], (ByteUtil.asUINT8(tbrRate
.getDatetime()[4]) >> 3) == 0); .getDatetime()[4]) >> 3) == 0);
@ -717,7 +739,12 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
entry.addDecodedData("Object", tbr); entry.addDecodedData("Object", tbr);
tbrPreviousRecord = null; entry.addDecodedData("Rate 1: ", tbrRate.getHead()[0] * 0.025);
entry.addDecodedData("Rate 2: ", ByteUtil.asUINT8(tbrRate.getHead()[0]) * 0.025d);
entry.addDecodedData("Rate 1.b: ", tbrRate.getHead()[0]);
entry.addDecodedData("Rate 2.b: ", ByteUtil.asUINT8(tbrRate.getHead()[0]));
entry.addDecodedData("Rate 3: ", (ByteUtil.asUINT8(tbrRate.getHead()[0])) / 40.0d);
} }
@ -743,13 +770,16 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
LocalDateTime atdate = new LocalDateTime(year, month, dayOfMonth, hour, minutes, seconds); LocalDateTime atdate = new LocalDateTime(year, month, dayOfMonth, hour, minutes, seconds);
entry.setLocalDateTime(atdate); entry.setLocalDateTime(atdate); // TODO remove
entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds));
} else if (entry.getDateTimeLength() == 2) { } else if (entry.getDateTimeLength() == 2) {
int low = ByteUtil.asUINT8(dt[0]) & 0x1F; int low = ByteUtil.asUINT8(dt[0]) & 0x1F;
int mhigh = (ByteUtil.asUINT8(dt[0]) & 0xE0) >> 4; int mhigh = (ByteUtil.asUINT8(dt[0]) & 0xE0) >> 4;
int mlow = (ByteUtil.asUINT8(dt[1]) & 0x80) >> 7; int mlow = (ByteUtil.asUINT8(dt[1]) & 0x80) >> 7;
int month = mhigh + mlow; int month = mhigh + mlow;
int dayOfMonth = low + 1; // int dayOfMonth = low + 1;
int dayOfMonth = dt[0] & 0x1F;
int year = 2000 + (ByteUtil.asUINT8(dt[1]) & 0x7F); int year = 2000 + (ByteUtil.asUINT8(dt[1]) & 0x7F);
// LocalDate rval = new LocalDate(year, month, dayOfMonth); // LocalDate rval = new LocalDate(year, month, dayOfMonth);
@ -758,7 +788,21 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
// int month = (((dt[0] & 0xE0) >> 4) + ((dt[1] & 0x80) >> 7)); // int month = (((dt[0] & 0xE0) >> 4) + ((dt[1] & 0x80) >> 7));
// int year = fix2DigitYear(dt[1] & 0x3F); // int year = fix2DigitYear(dt[1] & 0x3F);
LocalDateTime atdate = new LocalDateTime(year, month, dayOfMonth, 0, 0); LocalDateTime atdate = null;
LOG.debug("DT: {} {} {}", year, month, dayOfMonth);
if (dayOfMonth == 32) {
// FIXME remove
LOG.debug("Entry: {} = [{}] {}", entry.getEntryType().name(), ByteUtil.getHex(entry.getRawData()),
entry);
}
if (entry.getEntryType() == PumpHistoryEntryType.EndResultTotals) {
atdate = new LocalDateTime(year, month, dayOfMonth, 23, 59, 59);
} else {
atdate = new LocalDateTime(year, month, dayOfMonth, 0, 0);
}
entry.setLocalDateTime(atdate); entry.setLocalDateTime(atdate);
} else { } else {

View file

@ -6,6 +6,8 @@ import org.joda.time.LocalDateTime;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.MedtronicHistoryEntry; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.MedtronicHistoryEntry;
@ -35,9 +37,9 @@ public class PumpHistoryEntry extends MedtronicHistoryEntry {
private static Logger LOG = LoggerFactory.getLogger(PumpHistoryEntry.class); private static Logger LOG = LoggerFactory.getLogger(PumpHistoryEntry.class);
@Expose
private PumpHistoryEntryType entryType; private PumpHistoryEntryType entryType;
private Integer opCode; // this is set only when we have unknown entry... private Integer opCode; // this is set only when we have unknown entry...
// private LocalDateTime timeOfEntry;
private int offset; private int offset;
@ -77,15 +79,6 @@ public class PumpHistoryEntry extends MedtronicHistoryEntry {
} }
// public PumpTimeStampedRecord getHistoryEntryDetails() {
// return historyEntryDetails;
// }
//
//
// public void setHistoryEntryDetails(PumpTimeStampedRecord historyEntryDetails) {
// this.historyEntryDetails = historyEntryDetails;
// }
public int getOffset() { public int getOffset() {
return offset; return offset;
} }
@ -137,11 +130,16 @@ public class PumpHistoryEntry extends MedtronicHistoryEntry {
return this.dateTime.isAfter(dateTimeIn); return this.dateTime.isAfter(dateTimeIn);
} }
public boolean isAfter(long atechDateTime) {
return atechDateTime > this.atechDateTime;
}
public static class Comparator implements java.util.Comparator<PumpHistoryEntry> { public static class Comparator implements java.util.Comparator<PumpHistoryEntry> {
@Override @Override
public int compare(PumpHistoryEntry o1, PumpHistoryEntry o2) { public int compare(PumpHistoryEntry o1, PumpHistoryEntry o2) {
return o2.dateTime.compareTo(o1.dateTime); return (int)(o2.atechDateTime - o1.atechDateTime);
} }
} }
} }

View file

@ -61,8 +61,8 @@ public enum PumpHistoryEntryType // implements CodeEnum
LowBattery(0x19, "LowBattery"), // LowBattery(0x19, "LowBattery"), //
BatteryActivity(0x1a, "Battery Activity"), // BatteryActivity(0x1a, "Battery Activity"), //
SetAutoOff(0x1b, "SetAutoOff"), // SetAutoOff(0x1b, "SetAutoOff"), //
PumpSuspend(0x1e, "PumpSuspend"), // PumpSuspend(0x1e, "Pump Suspend"), //
PumpResume(0x1f, "PumpResume"), // PumpResume(0x1f, "Pump Resume"), //
SelfTest(0x20, "SelfTest"), // SelfTest(0x20, "SelfTest"), //
Rewind(0x21, "Rewind"), // Rewind(0x21, "Rewind"), //
ClearSettings(0x22, "ClearSettings"), // 8? ClearSettings(0x22, "ClearSettings"), // 8?
@ -78,7 +78,7 @@ public enum PumpHistoryEntryType // implements CodeEnum
EventUnknown_MM512_0x2f(0x2f), // EventUnknown_MM512_0x2f(0x2f), //
ChangeBGReminderOffset(0x31), // ChangeBGReminderOffset(0x31), //
ChangeAlarmClockTime(0x32), // ChangeAlarmClockTime(0x32), //
TempBasalRate(0x33, "TempBasal", 2, 5, 1), // TempBasalRate(0x33, "Temp Basal Rate", 2, 5, 1), //
LowReservoir(0x34), // LowReservoir(0x34), //
ChangeMeterId(0x36), // ChangeMeterId(0x36), //
@ -88,7 +88,7 @@ public enum PumpHistoryEntryType // implements CodeEnum
EventUnknown_MM512_0x3b(0x3b), // EventUnknown_MM512_0x3b(0x3b), //
ChangeParadigmLinkID(0x3c, 2, 5, 14), // V3 ? V6: 2,5,14 ChangeParadigmLinkID(0x3c, 2, 5, 14), // V3 ? V6: 2,5,14
BGReceived(0x3f, "BGReceived", 2, 5, 3), // Ian3F BGReceived(0x3f, "BG Received", 2, 5, 3), // Ian3F
JournalEntryMealMarker(0x40, 2, 5, 2), // JournalEntryMealMarker(0x40, 2, 5, 2), //
JournalEntryExerciseMarker(0x41, 2, 5, 1), // ?? JournalEntryExerciseMarkerPumpEvent JournalEntryExerciseMarker(0x41, 2, 5, 1), // ?? JournalEntryExerciseMarkerPumpEvent
JournalEntryInsulinMarker(0x42, 2, 5, 1), // ?? InsulinMarkerEvent JournalEntryInsulinMarker(0x42, 2, 5, 1), // ?? InsulinMarkerEvent
@ -116,7 +116,7 @@ public enum PumpHistoryEntryType // implements CodeEnum
ChangeBolusScrollStepSize(0x57), // ChangeBolusScrollStepSize(0x57), //
// V4 // V4
// Andy58(0x58, "Unknown", 13, 5, 0), // TODO is this one really there ??? // Andy58(0x58, "Unknown", 13, 5, 0), // TO DO is this one really there ???
BolusWizardChange(0x5a, "BolusWizard", 2, 5, 117), // V2: 522+[B=143] BolusWizardChange(0x5a, "BolusWizard", 2, 5, 117), // V2: 522+[B=143]
BolusWizardBolusEstimate(0x5b, "BolusWizardBolusEstimate", 2, 5, 13), // 15 // V2: 523+[B=15] BolusWizardBolusEstimate(0x5b, "BolusWizardBolusEstimate", 2, 5, 13), // 15 // V2: 523+[B=15]
@ -125,7 +125,7 @@ public enum PumpHistoryEntryType // implements CodeEnum
ChangeVariableBolus(0x5e), // ChangeVariableBolus(0x5e), //
ChangeAudioBolus(0x5f, "EasyBolusEnabled"), // V3 ? ChangeAudioBolus(0x5f, "EasyBolusEnabled"), // V3 ?
ChangeBGReminderEnable(0x60), // questionable60 ChangeBGReminderEnable(0x60), // questionable60
ChangeAlarmClockEnable((byte)0x61), // ChangeAlarmClockEnable(0x61), //
ChangeTempBasalType((byte)0x62), // ChangeTempBasalTypePumpEvent ChangeTempBasalType((byte)0x62), // ChangeTempBasalTypePumpEvent
ChangeAlarmNotifyMode(0x63), // ChangeAlarmNotifyMode(0x63), //
ChangeTimeFormat(0x64), // ChangeTimeFormat(0x64), //
@ -134,10 +134,10 @@ public enum PumpHistoryEntryType // implements CodeEnum
ChangeBolusReminderTime((byte)0x67, 2, 5, 2), // 9 ChangeBolusReminderTime((byte)0x67, 2, 5, 2), // 9
DeleteBolusReminderTime((byte)0x68, 2, 5, 2), // 9 DeleteBolusReminderTime((byte)0x68, 2, 5, 2), // 9
BolusReminder(0x69, 2, 5, 0), // Ian69 BolusReminder(0x69, 2, 5, 0), // Ian69
DeleteAlarmClockTime(0x6a, "DeleteAlarmClockTime", 2, 5, 7), // 14 DeleteAlarmClockTime(0x6a, "Delete Alarm Clock Time", 2, 5, 7), // 14
DailyTotals512(0x6c, "Daily Totals 512", 0, 0, 36), // DailyTotals515(0x6c, "Daily Totals 515", 0, 0, 36), //
DailyTotals522(0x6d, "Daily Totals 522", 1, 2, 41), // // hack1(0x6d, "hack1", 46, 5, 0), DailyTotals522(0x6d, "Daily Totals 522", 1, 2, 41), // // hack1(0x6d, "hack1", 46, 5, 0), // 1,2,41
DailyTotals523(0x6e, "Daily Totals 523", 1, 2, 49), // 1102014-03-17T00:00:00 DailyTotals523(0x6e, "Daily Totals 523", 1, 2, 49), // 1102014-03-17T00:00:00
ChangeCarbUnits((byte)0x6f), // ChangeCarbUnits((byte)0x6f), //
@ -147,12 +147,12 @@ public enum PumpHistoryEntryType // implements CodeEnum
ChangeWatchdogEnable((byte)0x7c), // ChangeWatchdogEnable((byte)0x7c), //
ChangeOtherDeviceID((byte)0x7d, 2, 5, 30), // ChangeOtherDeviceID((byte)0x7d, 2, 5, 30), //
ChangeWatchdogMarriageProfile((byte)0x81, 2, 5, 5), // 12 // ChangeWatchdogMarriageProfile(0x81, 2, 5, 5), // 12
DeleteOtherDeviceID((byte)0x82, 2, 5, 5), // // DeleteOtherDeviceID(0x82, 2, 5, 5), //
ChangeCaptureEventEnable((byte)0x83), // // ChangeCaptureEventEnable(0x83), //
EventUnknown_MM512_0x88((byte)0x88), // EventUnknown_MM512_0x88(0x88), //
EventUnknown_MM512_0x94((byte)0x94), // EventUnknown_MM512_0x94(0x94), //
// IanA8(0xA8, "xx", 10, 5, 0), // // IanA8(0xA8, "xx", 10, 5, 0), //
// Andy90(0x90, "Unknown", 7, 5, 0), // Andy90(0x90, "Unknown", 7, 5, 0),
@ -165,6 +165,12 @@ public enum PumpHistoryEntryType // implements CodeEnum
EventUnknown_MM522_0xE8(0xe8, 2, 5, 25), // EventUnknown_MM522_0xE8(0xe8, 2, 5, 25), //
ReadOtherDevicesIDs(0xF0, ""), // ?
readCaptureEventEnabled(0xF1), // ?
changeCaptureEventEnable(0xF2), // ?
readOtherDevicesStatus(0xF3), // ?
TempBasalCombined(0xFE, "TempBasalCombined"), //
UnknownBasePacket(0xFF, "Unknown Base Packet"); UnknownBasePacket(0xFF, "Unknown Base Packet");
// private PumpHistoryEntryType(String description, List<Integer> opCode, // private PumpHistoryEntryType(String description, List<Integer> opCode,
@ -263,6 +269,37 @@ public enum PumpHistoryEntryType // implements CodeEnum
// } // }
// //
public static boolean isAAPSRelevantEntry(PumpHistoryEntryType entryType) {
return (entryType == PumpHistoryEntryType.Bolus || // Treatments
entryType == PumpHistoryEntryType.TempBasalRate || //
entryType == PumpHistoryEntryType.TempBasalDuration || //
entryType == PumpHistoryEntryType.Prime || // Pump Status Change
entryType == PumpHistoryEntryType.PumpSuspend || //
entryType == PumpHistoryEntryType.PumpResume || //
entryType == PumpHistoryEntryType.Rewind || //
entryType == PumpHistoryEntryType.NoDeliveryAlarm || // no delivery
entryType == PumpHistoryEntryType.BasalProfileStart || //
entryType == PumpHistoryEntryType.ChangeTime || // Time Change
entryType == PumpHistoryEntryType.NewTimeSet || //
entryType == PumpHistoryEntryType.SelectBasalProfile || // Settings
entryType == PumpHistoryEntryType.ClearSettings || //
entryType == PumpHistoryEntryType.SaveSettings || //
entryType == PumpHistoryEntryType.ChangeMaxBolus || //
entryType == PumpHistoryEntryType.ChangeMaxBasal || //
entryType == PumpHistoryEntryType.ChangeTempBasalType || //
entryType == PumpHistoryEntryType.ChangeBasalProfile_NewProfile || // Basal profile
entryType == PumpHistoryEntryType.DailyTotals515 || // Daily Totals
entryType == PumpHistoryEntryType.DailyTotals522 || //
entryType == PumpHistoryEntryType.DailyTotals523 || //
entryType == PumpHistoryEntryType.EndResultTotals);
}
public static boolean isRelevantEntry() { public static boolean isRelevantEntry() {
return true; return true;
} }

View file

@ -8,6 +8,8 @@ import org.joda.time.LocalDateTime;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
/** /**
* Created by andy on 9/23/18. * Created by andy on 9/23/18.
*/ */
@ -48,7 +50,7 @@ public class PumpHistoryResult {
public void addHistoryEntries(List<PumpHistoryEntry> entries) { public void addHistoryEntries(List<PumpHistoryEntry> entries) {
this.unprocessedEntries = entries; this.unprocessedEntries = entries;
LOG.debug("PumpHistoryResult. Unprocessed entries: {}", entries); LOG.debug("PumpHistoryResult. Unprocessed entries: {}", MedtronicPumpPlugin.gsonInstance.toJson(entries));
processEntries(); processEntries();
} }
@ -115,8 +117,15 @@ public class PumpHistoryResult {
public PumpHistoryEntry getLatestEntry() { public PumpHistoryEntry getLatestEntry() {
if (this.validEntries == null || this.validEntries.size() == 0) if (this.validEntries == null || this.validEntries.size() == 0)
return null; return null;
else else {
return this.validEntries.get(0); return this.validEntries.get(0);
// PumpHistoryEntry pumpHistoryEntry = this.validEntries.get(0);
//
// if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.EndResultTotals)
// return pumpHistoryEntry;
// else
// return this.validEntries.get(1);
}
} }

View file

@ -45,15 +45,15 @@ public class MedtronicUIPostprocessor {
switch (uiTask.commandType) { switch (uiTask.commandType) {
case SetBasalProfileSTD: { case SetBasalProfileSTD: {
Boolean response = (Boolean) uiTask.returnData; Boolean response = (Boolean)uiTask.returnData;
if (response) { if (response) {
BasalProfile basalProfile = (BasalProfile) uiTask.getParameter(0); BasalProfile basalProfile = (BasalProfile)uiTask.getParameter(0);
pumpStatus.basalsByHour = basalProfile.getProfilesByHour(); pumpStatus.basalsByHour = basalProfile.getProfilesByHour();
} }
} }
break; break;
case GetBasalProfileSTD: { case GetBasalProfileSTD: {
BasalProfile basalProfile = (BasalProfile)uiTask.returnData; BasalProfile basalProfile = (BasalProfile)uiTask.returnData;
@ -119,7 +119,7 @@ public class MedtronicUIPostprocessor {
// no postprocessing // no postprocessing
default: default:
LOG.warn("Post-processing not implemented for {}.", uiTask.commandType.name()); LOG.trace("Post-processing not implemented for {}.", uiTask.commandType.name());
} }
@ -135,15 +135,14 @@ public class MedtronicUIPostprocessor {
long currentTimeMillis = System.currentTimeMillis(); long currentTimeMillis = System.currentTimeMillis();
long diff = Math.abs(d1.getTime() - currentTimeMillis); long diff = Math.abs(d1.getTime() - currentTimeMillis);
LOG.warn("Pump Time: " + ldt + ", DeviceTime=" + d1 + // LOG.debug("Pump Time: " + ldt + ", DeviceTime=" + d1 + //
// ", epoch: " + d1.getTime() + ", current: " + currentTimeMillis + //
", diff: " + diff / 1000 + " s"); ", diff: " + diff / 1000 + " s");
if (diff >= 10 * 60 * 1000) { if (diff >= 10 * 60 * 1000) {
LOG.debug("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")"); LOG.warn("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")");
sendNotification(MedtronicNotificationType.PumpWrongTimeUrgent); sendNotification(MedtronicNotificationType.PumpWrongTimeUrgent);
} else if (diff >= 4 * 60 * 1000) { } else if (diff >= 4 * 60 * 1000) {
LOG.debug("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")"); LOG.warn("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")");
sendNotification(MedtronicNotificationType.PumpWrongTimeNormal); sendNotification(MedtronicNotificationType.PumpWrongTimeNormal);
} }

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui; package info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
@ -125,6 +127,12 @@ public class MedtronicUITask {
} }
break; break;
case GetHistoryData: {
returnData = communicationManager.getPumpHistory((PumpHistoryEntry)parameters[0],
(LocalDateTime)parameters[1]);
}
break;
default: { default: {
LOG.warn("This commandType is not supported (yet) - {}.", commandType); LOG.warn("This commandType is not supported (yet) - {}.", commandType);
// invalid = true; // invalid = true;

View file

@ -1,11 +1,25 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data; package info.nightscout.androidaps.plugins.PumpMedtronic.data;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import org.joda.time.LocalDateTime; import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Splitter;
import info.nightscout.androidaps.plugins.PumpCommon.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntryType;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryResult;
//import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
/** /**
* Created by andy on 10/12/18. * Created by andy on 10/12/18.
@ -13,43 +27,263 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHi
public class MedtronicHistoryData { public class MedtronicHistoryData {
List<PumpHistoryEntry> history = null; private static final Logger LOG = LoggerFactory.getLogger(MedtronicHistoryData.class);
private boolean suspended = false;
private boolean relevantConfigurationChanged = false; private List<PumpHistoryEntry> allHistory = null;
private boolean basalProfileChanged = true; private List<PumpHistoryEntry> newHistory = null;
private LocalDateTime lastHistoryRecordTime; private LocalDateTime lastHistoryRecordTime;
private boolean isInit = false;
private static final int OLD_HISTORY_SIZE = 50;
public MedtronicHistoryData() { public MedtronicHistoryData() {
this.history = new ArrayList<>(); this.allHistory = new ArrayList<>();
} }
// TODO /**
public boolean isSuspended() { * Add New History entries
return suspended; *
* @param result PumpHistoryResult instance
*/
public void addNewHistory(PumpHistoryResult result) {
this.newHistory = result.getValidEntries();
showLogs("List of history (before filtering): ", MedtronicPumpPlugin.gsonInstance.toJson(this.newHistory));
}
public static void showLogs(String header, String data) {
if (header != null) {
LOG.debug(header);
}
for (final String token : Splitter.fixedLength(3500).split(data)) {
LOG.debug("{}", token);
}
}
public void filterNewEntries() {
List<PumpHistoryEntry> newHistory2 = new ArrayList<>();
List<PumpHistoryEntry> TBRs = new ArrayList<>();
LocalDateTime localDateTime = new LocalDateTime();
for (PumpHistoryEntry pumpHistoryEntry : newHistory) {
PumpHistoryEntryType type = pumpHistoryEntry.getEntryType();
if (PumpHistoryEntryType.isAAPSRelevantEntry(type)) {
if (type == PumpHistoryEntryType.TempBasalRate || type == PumpHistoryEntryType.TempBasalDuration) {
TBRs.add(pumpHistoryEntry);
} else {
if (type == PumpHistoryEntryType.EndResultTotals) {
if (!DateTimeUtil.isSameDay(localDateTime, pumpHistoryEntry.getLocalDateTime())) {
newHistory2.add(pumpHistoryEntry);
}
} else {
newHistory2.add(pumpHistoryEntry);
}
}
}
}
TBRs = processTBRs(TBRs);
newHistory2.addAll(TBRs);
this.newHistory = newHistory2;
sort(this.newHistory);
LOG.debug("New History entries found: {}", this.newHistory.size());
showLogs("List of history (after filtering): ", MedtronicPumpPlugin.gsonInstance.toJson(this.newHistory));
}
public void finalizeNewHistoryRecords() {
List<PumpHistoryEntry> filteredListByLastRecord = getFilteredListByLastRecord((PumpHistoryEntryType)null);
if (filteredListByLastRecord.size() == 0)
return;
List<PumpHistoryEntry> outList = new ArrayList<>();
if (allHistory.size() > OLD_HISTORY_SIZE) {
for (int i = 0; i < OLD_HISTORY_SIZE; i++) {
outList.add(allHistory.get(i));
}
}
outList.addAll(filteredListByLastRecord);
this.allHistory.clear();
this.allHistory.addAll(outList);
this.sort(this.allHistory);
} }
// TODO implement logic here fror config changes
public boolean hasRelevantConfigurationChanged() { public boolean hasRelevantConfigurationChanged() {
return relevantConfigurationChanged;
return getStateFromFilteredList( //
PumpHistoryEntryType.SelectBasalProfile, //
PumpHistoryEntryType.ClearSettings, //
PumpHistoryEntryType.SaveSettings, //
PumpHistoryEntryType.ChangeMaxBolus, //
PumpHistoryEntryType.ChangeMaxBasal, //
PumpHistoryEntryType.ChangeTempBasalType);
} }
public void resetRelevantConfigurationChanged() { // TODO This logic might not be working correctly
relevantConfigurationChanged = false; public boolean isPumpSuspended(Boolean wasPumpSuspended) {
if (wasPumpSuspended == null) { // suspension status not known
List<PumpHistoryEntry> items = getFilteredItems(PumpHistoryEntryType.Bolus, //
PumpHistoryEntryType.TempBasalCombined, //
PumpHistoryEntryType.Prime, //
PumpHistoryEntryType.PumpSuspend, //
PumpHistoryEntryType.PumpResume, //
PumpHistoryEntryType.Rewind, //
PumpHistoryEntryType.NoDeliveryAlarm, //
PumpHistoryEntryType.BasalProfileStart);
if (items.size() == 0)
return wasPumpSuspended == null ? false : wasPumpSuspended;
PumpHistoryEntry pumpHistoryEntry = items.get(0);
return !(pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.TempBasalCombined || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.BasalProfileStart || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.Bolus || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.PumpResume);
} else {
List<PumpHistoryEntry> items = getFilteredItems(PumpHistoryEntryType.Bolus, //
PumpHistoryEntryType.TempBasalCombined, //
PumpHistoryEntryType.Prime, //
PumpHistoryEntryType.PumpSuspend, //
PumpHistoryEntryType.PumpResume, //
PumpHistoryEntryType.Rewind, //
PumpHistoryEntryType.NoDeliveryAlarm, //
PumpHistoryEntryType.BasalProfileStart);
if (wasPumpSuspended) {
if (items.size() == 0)
return wasPumpSuspended == null ? false : wasPumpSuspended;
PumpHistoryEntry pumpHistoryEntry = items.get(0);
if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.TempBasalCombined || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.BasalProfileStart || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.Bolus || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.PumpResume)
return false;
else
return true;
} else {
PumpHistoryEntry pumpHistoryEntry = items.get(0);
if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.NoDeliveryAlarm || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.PumpSuspend || //
pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.Prime)
return true;
}
}
// FIXME
return false;
} }
// TODO implement logic to see if Basalrates changed from last time public List<PumpHistoryEntry> getTDDs() {
return getFilteredListByLastRecord(PumpHistoryEntryType.EndResultTotals);
}
// FIXME remove
public List<PumpHistoryEntry> getTDDs2() {
return getFilteredListByLastRecord(PumpHistoryEntryType.DailyTotals515, PumpHistoryEntryType.DailyTotals522,
PumpHistoryEntryType.DailyTotals523);
}
public List<PumpHistoryEntry> getTreatments() {
return getFilteredListByLastRecord( //
PumpHistoryEntryType.Bolus, //
PumpHistoryEntryType.TempBasalCombined);
}
/*
* entryType == PumpHistoryEntryType.Bolus || // Treatments
* entryType == PumpHistoryEntryType.TempBasalRate || //
* entryType == PumpHistoryEntryType.TempBasalDuration || //
*
* entryType == PumpHistoryEntryType.Prime || // Pump Status Change
* entryType == PumpHistoryEntryType.PumpSuspend || //
* entryType == PumpHistoryEntryType.PumpResume || //
* entryType == PumpHistoryEntryType.Rewind || //
* entryType == PumpHistoryEntryType.NoDeliveryAlarm || // no delivery
* entryType == PumpHistoryEntryType.BasalProfileStart || //
*
* entryType == PumpHistoryEntryType.ChangeTime || // Time Change
* entryType == PumpHistoryEntryType.NewTimeSet || //
*
* entryType == PumpHistoryEntryType.SelectBasalProfile || // Settings
* entryType == PumpHistoryEntryType.ClearSettings || //
* entryType == PumpHistoryEntryType.SaveSettings || //
* entryType == PumpHistoryEntryType.ChangeMaxBolus || //
* entryType == PumpHistoryEntryType.ChangeMaxBasal || //
* entryType == PumpHistoryEntryType.ChangeTempBasalType || //
*
* entryType == PumpHistoryEntryType.ChangeBasalProfile_NewProfile || // Basal profile
*
* entryType == PumpHistoryEntryType.DailyTotals512 || // Daily Totals
* entryType == PumpHistoryEntryType.DailyTotals522 || //
* entryType == PumpHistoryEntryType.DailyTotals523 || //
* entryType == PumpHistoryEntryType.EndResultTotals
*/
public boolean hasBasalProfileChanged() { public boolean hasBasalProfileChanged() {
return basalProfileChanged;
return getStateFromFilteredList(PumpHistoryEntryType.ChangeBasalProfile_NewProfile);
} }
public void resetBasalProfileChanged() { public boolean hasPumpTimeChanged() {
basalProfileChanged = true; // FIXME when this works this should reset to false
return getStateFromFilteredList(PumpHistoryEntryType.NewTimeSet, //
PumpHistoryEntryType.ChangeTime);
} }
@ -59,8 +293,103 @@ public class MedtronicHistoryData {
} }
public LocalDateTime getLastHistoryRecordTime() { public void setIsInInit(boolean init) {
this.isInit = init;
}
return lastHistoryRecordTime;
// HELPER METHODS
private void sort(List<PumpHistoryEntry> list) {
Collections.sort(list, new PumpHistoryEntry.Comparator());
}
private List<PumpHistoryEntry> processTBRs(List<PumpHistoryEntry> TBRs_Input) {
List<PumpHistoryEntry> TBRs = new ArrayList<>();
Map<String, PumpHistoryEntry> map = new HashMap<>();
for (PumpHistoryEntry pumpHistoryEntry : TBRs_Input) {
if (map.containsKey(pumpHistoryEntry.DT)) {
MedtronicPumpHistoryDecoder.decodeTempBasal(map.get(pumpHistoryEntry.DT), pumpHistoryEntry);
pumpHistoryEntry.setEntryType(PumpHistoryEntryType.TempBasalCombined);
TBRs.add(pumpHistoryEntry);
map.remove(pumpHistoryEntry.DT);
} else {
map.put(pumpHistoryEntry.DT, pumpHistoryEntry);
}
}
return TBRs;
}
private List<PumpHistoryEntry> getFilteredItems(PumpHistoryEntryType... entryTypes) {
return getFilteredItems(this.newHistory, entryTypes);
}
private List<PumpHistoryEntry> getFilteredListByLastRecord(PumpHistoryEntryType... entryTypes) {
if (this.lastHistoryRecordTime == null) {
return getFilteredItems(entryTypes);
} else {
return getFilteredItems(this.lastHistoryRecordTime, entryTypes);
}
}
private boolean getStateFromFilteredList(PumpHistoryEntryType... entryTypes) {
if (isInit) {
return false;
} else {
List<PumpHistoryEntry> filteredItems = getFilteredItems(entryTypes);
return filteredItems.size() > 0;
}
}
private List<PumpHistoryEntry> getFilteredItems(LocalDateTime dateTime, PumpHistoryEntryType... entryTypes) {
PumpHistoryResult phr = new PumpHistoryResult(null, dateTime);
return getFilteredItems(phr.getValidEntries(), entryTypes);
}
private List<PumpHistoryEntry> getFilteredItems(List<PumpHistoryEntry> inList, PumpHistoryEntryType... entryTypes) {
// LOG.debug("InList: " + inList.size());
List<PumpHistoryEntry> outList = new ArrayList<>();
if (inList != null && inList.size() > 0) {
for (PumpHistoryEntry pumpHistoryEntry : inList) {
if (entryTypes != null) {
for (PumpHistoryEntryType pumpHistoryEntryType : entryTypes) {
if (pumpHistoryEntry.getEntryType() == pumpHistoryEntryType) {
outList.add(pumpHistoryEntry);
break;
}
}
} else {
outList.add(pumpHistoryEntry);
}
}
}
// LOG.debug("OutList: " + outList.size());
return outList;
}
public List<PumpHistoryEntry> getNewHistoryEntries() {
return this.newHistory;
} }
} }

View file

@ -7,6 +7,8 @@ import org.joda.time.Instant;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.FabricUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.FabricUtil;
@ -18,23 +20,24 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
* There are three basal profiles stored on the pump. (722 only?) They are all parsed the same, the user just has 3 to * There are three basal profiles stored on the pump. (722 only?) They are all parsed the same, the user just has 3 to
* choose from: Standard, A, and B * choose from: Standard, A, and B
* <p> * <p>
* The byte array seems to be 21 three byte entries long, plus a zero? If the profile is completely empty, it should * The byte array is 48 times three byte entries long, plus a zero? If the profile is completely empty, it should have
* have one entry: [0,0,0x3F] (?) The first entry of [0,0,0] marks the end of the used entries. * one entry: [0,0,0x3F]. The first entry of [0,0,0] marks the end of the used entries.
* <p> * <p>
* Each entry is assumed to span from the specified start time to the start time of the next entry, or to midnight if * Each entry is assumed to span from the specified start time to the start time of the next entry, or to midnight if
* there are no more entries. * there are no more entries.
* <p> * <p>
* Individual entries are of the form [r,z,m] where r is the rate (in 0.025 U increments) z is zero (?) m is the start * Individual entries are of the form [r,z,m] where r is the rate (in 0.025 U increments) z is zero (?) m is the start
* time-of-day for the basal rate period (in 30 minute increments?) * time-of-day for the basal rate period (in 30 minute increments)
*/ */
public class BasalProfile { public class BasalProfile {
public static final int MAX_RAW_DATA_SIZE = (48 * 3) + 1;
// private static final String TAG = "BasalProfile";
private static final Logger LOG = LoggerFactory.getLogger(BasalProfile.class); private static final Logger LOG = LoggerFactory.getLogger(BasalProfile.class);
public static final int MAX_RAW_DATA_SIZE = (48 * 3) + 1;
private static final boolean DEBUG_BASALPROFILE = false; private static final boolean DEBUG_BASALPROFILE = false;
protected byte[] mRawData; // store as byte array to make transport (via parcel) easier @Expose
List<BasalProfileEntry> listEntries; private byte[] mRawData; // store as byte array to make transport (via parcel) easier
private List<BasalProfileEntry> listEntries;
public BasalProfile() { public BasalProfile() {
@ -286,15 +289,6 @@ public class BasalProfile {
} }
} }
// StringBuilder sb = new StringBuilder();
//
// for (int i = 0; i < 24; i++) {
// sb.append("" + i + "=" + basalByHour[i]);
// sb.append("\n");
// }
//
// System.out.println("Basal Profile: \n" + sb.toString());
return basalByHour; return basalByHour;
} }

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BatteryType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BatteryType;
/** /**
@ -8,6 +10,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BatteryType;
public class BatteryStatusDTO { public class BatteryStatusDTO {
@Expose
public BatteryStatusType batteryStatusType; public BatteryStatusType batteryStatusType;
public double voltage; public double voltage;

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType;
@ -26,10 +28,15 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType;
public class BolusDTO extends PumpTimeStampedRecord { public class BolusDTO extends PumpTimeStampedRecord {
@Expose
private Float requestedAmount; private Float requestedAmount;
@Expose
private Float deliveredAmount; private Float deliveredAmount;
@Expose
private Float immediateAmount; // when Multiwave this is used private Float immediateAmount; // when Multiwave this is used
@Expose
private Integer duration; private Integer duration;
@Expose
private PumpBolusType bolusType; private PumpBolusType bolusType;
private Float insulinOnBoard; private Float insulinOnBoard;

View file

@ -0,0 +1,147 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntryType;
/**
* Created by andy on 11/3/18.
*/
public class DailyTotalsDTO {
private static final Logger LOG = LoggerFactory.getLogger(DailyTotalsDTO.class);
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs,
// Bolus=1.7, Fodd, Corr, Manual=1.7,
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
Double bgAvg;
Double bgLow;
Double bgHigh;
Integer bgCount;
Double sensorAvg;
Double sensorMin;
Double sensorMax;
Integer sensorCalcCount;
Integer sensorDataCount;
Double insulinTotal;
Double insulinBasal;
Double insulinBolus;
Double insulinCarbs;
Double bolusTotal;
Double bolusFood;
Double bolusCorrection;
Double bolusManual;
Integer bolusCount;
Integer bolusCountFoodOrCorr;
// Integer bolusCountCorr;
Integer bolusCountFoodAndCorr;
Integer bolusCountManual;
public DailyTotalsDTO(PumpHistoryEntryType entryType, byte[] data) {
switch (entryType) {
case DailyTotals515:
decodeData512(data);
break;
case DailyTotals522:
decodeData522(data);
break;
case DailyTotals523:
decodeData523(data);
break;
default:
break;
}
}
private void decodeData512(byte[] data) {
LOG.debug("Can't decode DailyTotals512: Body={}", ByteUtil.getHex(data));
}
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs,
// Bolus=1.7[18,19], Fodd, Corr, Manual=1.7[27,28],
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
private void decodeData522(byte[] data) {
// Double bgAvg;
// Double bgLow;
// Double bgHigh;
// Integer bgCount;
//
// Double sensorAvg;
// Double sensorMin;
// Double sensorMax;
// Integer sensorCalcCount;
// Integer sensorDataCount;
this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d;
this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d;
this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d;
// Double insulinCarbs;
this.bolusTotal = ByteUtil.toInt(data[17], data[18], data[19]) / 40.0d;
this.bolusFood = ByteUtil.toInt(data[21], data[22]) / 40.0d;
this.bolusCorrection = ByteUtil.toInt(data[23], data[24], data[25]) / 40.0d;
this.bolusManual = ByteUtil.toInt(data[26], data[27], data[28]) / 40.0d;
bolusCount = ByteUtil.asUINT8(data[30]);
bolusCountFoodOrCorr = ByteUtil.asUINT8(data[31]);
// Integer bolusCountCorr;
bolusCountFoodAndCorr = ByteUtil.asUINT8(data[32]);
bolusCountManual = ByteUtil.asUINT8(data[33]);
LOG.debug("{}", toString());
}
private void decodeData523(byte[] data) {
LOG.debug("Can't decode DailyTotals523: Body={}", ByteUtil.getHex(data));
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this) //
.add("bgAvg", bgAvg) //
.add("bgLow", bgLow) //
.add("bgHigh", bgHigh) //
.add("bgCount", bgCount) //
.add("sensorAvg", sensorAvg) //
.add("sensorMin", sensorMin) //
.add("sensorMax", sensorMax) //
.add("sensorCalcCount", sensorCalcCount) //
.add("sensorDataCount", sensorDataCount) //
.add("insulinTotal", insulinTotal) //
.add("insulinBasal", insulinBasal) //
.add("insulinBolus", insulinBolus) //
.add("insulinCarbs", insulinCarbs) //
.add("bolusTotal", bolusTotal) //
.add("bolusFood", bolusFood) //
.add("bolusCorrection", bolusCorrection) //
.add("bolusManual", bolusManual) //
.add("bolusCount", bolusCount) //
.add("bolusCountFoodOrCorr", bolusCountFoodOrCorr) //
.add("bolusCountFoodAndCorr", bolusCountFoodAndCorr) //
.add("bolusCountManual", bolusCountManual) //
.toString();
}
}

View file

@ -6,6 +6,9 @@ import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/** /**
@ -17,8 +20,11 @@ public class TempBasalPair {
private static final Logger LOG = LoggerFactory.getLogger(TempBasalPair.class); private static final Logger LOG = LoggerFactory.getLogger(TempBasalPair.class);
private double insulinRate = 0.0; @Expose
private double insulinRate = 0.0d;
@Expose
private int durationMinutes = 0; private int durationMinutes = 0;
@Expose
private boolean isPercent = false; private boolean isPercent = false;
@ -34,10 +40,12 @@ public class TempBasalPair {
* @param isPercent * @param isPercent
*/ */
public TempBasalPair(byte rateByte, int startTimeByte, boolean isPercent) { public TempBasalPair(byte rateByte, int startTimeByte, boolean isPercent) {
int rateInt = ByteUtil.asUINT8(rateByte);
if (isPercent) if (isPercent)
this.insulinRate = rateByte; this.insulinRate = rateByte;
else else
this.insulinRate = rateByte * 0.025; this.insulinRate = rateInt * 0.025;
this.durationMinutes = startTimeByte * 30; this.durationMinutes = startTimeByte * 30;
this.isPercent = isPercent; this.isPercent = isPercent;
} }

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
/**
* Created by andy on 11/3/18.
*/
public enum MedtronicCustomActionType implements CustomActionType {
WakeUpAndTune()
;
@Override
public String getKey() {
return this.name();
}
}

View file

@ -65,6 +65,8 @@ public class MedtronicPumpStatus extends PumpStatus {
private boolean isFrequencyUS = false; private boolean isFrequencyUS = false;
private Map<String, PumpType> medtronicPumpMap = null; private Map<String, PumpType> medtronicPumpMap = null;
private Map<String, MedtronicDeviceType> medtronicDeviceTypeMap = null; private Map<String, MedtronicDeviceType> medtronicDeviceTypeMap = null;
private RileyLinkTargetFrequency targetFrequency;
private boolean targetFrequencyChanged = false;
public MedtronicPumpStatus(PumpDescription pumpDescription) { public MedtronicPumpStatus(PumpDescription pumpDescription) {
@ -189,9 +191,15 @@ public class MedtronicPumpStatus extends PumpStatus {
this.pumpFrequency = pumpFrequency; this.pumpFrequency = pumpFrequency;
this.isFrequencyUS = pumpFrequency.equals(frequencies[0]); this.isFrequencyUS = pumpFrequency.equals(frequencies[0]);
RileyLinkUtil.setRileyLinkTargetFrequency(this.isFrequencyUS ? // RileyLinkTargetFrequency newTargetFrequency = this.isFrequencyUS ? //
RileyLinkTargetFrequency.Medtronic_US RileyLinkTargetFrequency.Medtronic_US
: RileyLinkTargetFrequency.Medtronic_WorldWide); : RileyLinkTargetFrequency.Medtronic_WorldWide;
if (targetFrequency == newTargetFrequency) {
RileyLinkUtil.setRileyLinkTargetFrequency(newTargetFrequency);
targetFrequencyChanged = true;
}
} }
} }
@ -228,7 +236,9 @@ public class MedtronicPumpStatus extends PumpStatus {
// LOG.debug("MedtronicPumpStatus::startService"); // LOG.debug("MedtronicPumpStatus::startService");
if (serialChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) { boolean ready = (!inPreInit && MedtronicUtil.getMedtronicService() != null);
if (serialChanged && ready) {
MedtronicUtil.getMedtronicService().setPumpIDString(this.serialNumber); // short operation MedtronicUtil.getMedtronicService().setPumpIDString(this.serialNumber); // short operation
serialChanged = false; serialChanged = false;
} }
@ -238,7 +248,13 @@ public class MedtronicPumpStatus extends PumpStatus {
rileyLinkAddressChanged = false; rileyLinkAddressChanged = false;
} }
return (rileyLinkAddressChanged == false && serialChanged == false); if (targetFrequencyChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
RileyLinkUtil.setRileyLinkTargetFrequency(targetFrequency);
RileyLinkUtil.getRileyLinkCommunicationManager().refreshRileyLinkTargetFrequency();
targetFrequencyChanged = false;
}
return (!rileyLinkAddressChanged && !serialChanged && !targetFrequencyChanged);
} }

View file

@ -92,9 +92,9 @@ public class RileyLinkMedtronicService extends RileyLinkService {
MainApp.gs(R.string.medtronic_pump_frequency_us)).equals(MainApp.gs(R.string.medtronic_pump_frequency_us)); MainApp.gs(R.string.medtronic_pump_frequency_us)).equals(MainApp.gs(R.string.medtronic_pump_frequency_us));
if (hasUSFrequency) if (hasUSFrequency)
this.rileyLinkTargetFrequency = RileyLinkTargetFrequency.Medtronic_US; RileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Medtronic_US);
else else
this.rileyLinkTargetFrequency = RileyLinkTargetFrequency.Medtronic_WorldWide; RileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Medtronic_WorldWide);
} }
@ -120,7 +120,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE);
// init rileyLinkCommunicationManager // init rileyLinkCommunicationManager
medtronicCommunicationManager = new MedtronicCommunicationManager(context, rfspy, rileyLinkTargetFrequency); medtronicCommunicationManager = new MedtronicCommunicationManager(context, rfspy);
} }

View file

@ -219,24 +219,6 @@ public class MedtronicUtil extends RileyLinkUtil {
} }
// @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) { public static byte[] buildCommandPayload(MessageType commandType, byte[] parameters) {
return buildCommandPayload(commandType.getValue(), parameters); return buildCommandPayload(commandType.getValue(), parameters);
} }
@ -463,6 +445,7 @@ public class MedtronicUtil extends RileyLinkUtil {
if (currentCommand != null) if (currentCommand != null)
historyRileyLink.add(new RLHistoryItem(currentCommand)); historyRileyLink.add(new RLHistoryItem(currentCommand));
} }

View file

@ -1,14 +1,16 @@
package info.nightscout.androidaps.plugins.PumpVirtual; package info.nightscout.androidaps.plugins.PumpVirtual;
import android.os.SystemClock; import java.util.List;
import com.squareup.otto.Subscribe;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import android.os.SystemClock;
import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -26,6 +28,8 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.Actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.Actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@ -41,6 +45,7 @@ import info.nightscout.utils.SP;
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class VirtualPumpPlugin extends PluginBase implements PumpInterface { public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
private Logger log = LoggerFactory.getLogger(L.PUMP); private Logger log = LoggerFactory.getLogger(L.PUMP);
Integer batteryPercent = 50; Integer batteryPercent = 50;
@ -51,16 +56,12 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
private long lastDataTime = 0; private long lastDataTime = 0;
private PumpDescription pumpDescription = new PumpDescription(); private PumpDescription pumpDescription = new PumpDescription();
public VirtualPumpPlugin() { public VirtualPumpPlugin() {
super(new PluginDescription() super(new PluginDescription().mainType(PluginType.PUMP).fragmentClass(VirtualPumpFragment.class.getName())
.mainType(PluginType.PUMP) .pluginName(R.string.virtualpump).shortName(R.string.virtualpump_shortname)
.fragmentClass(VirtualPumpFragment.class.getName()) .preferencesId(R.xml.pref_virtualpump).neverVisible(Config.NSCLIENT)
.pluginName(R.string.virtualpump) .description(R.string.description_pump_virtual));
.shortName(R.string.virtualpump_shortname)
.preferencesId(R.xml.pref_virtualpump)
.neverVisible(Config.NSCLIENT)
.description(R.string.description_pump_virtual)
);
pumpDescription.isBolusCapable = true; pumpDescription.isBolusCapable = true;
pumpDescription.bolusStep = 0.1d; pumpDescription.bolusStep = 0.1d;
@ -80,7 +81,6 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
pumpDescription.tempDurationStep30mAllowed = true; pumpDescription.tempDurationStep30mAllowed = true;
pumpDescription.tempMaxDuration = 24 * 60; pumpDescription.tempMaxDuration = 24 * 60;
pumpDescription.isSetBasalProfileCapable = true; pumpDescription.isSetBasalProfileCapable = true;
pumpDescription.basalStep = 0.01d; pumpDescription.basalStep = 0.01d;
pumpDescription.basalMinimumRate = 0.01d; pumpDescription.basalMinimumRate = 0.01d;
@ -91,6 +91,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
pumpDescription.is30minBasalRatesCapable = true; pumpDescription.is30minBasalRatesCapable = true;
} }
public static VirtualPumpPlugin getPlugin() { public static VirtualPumpPlugin getPlugin() {
if (plugin == null) if (plugin == null)
plugin = new VirtualPumpPlugin(); plugin = new VirtualPumpPlugin();
@ -98,19 +99,23 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return plugin; return plugin;
} }
private void loadFakingStatus() { private void loadFakingStatus() {
fromNSAreCommingFakedExtendedBoluses = SP.getBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, false); fromNSAreCommingFakedExtendedBoluses = SP.getBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, false);
} }
public boolean getFakingStatus() { public boolean getFakingStatus() {
return fromNSAreCommingFakedExtendedBoluses; return fromNSAreCommingFakedExtendedBoluses;
} }
public void setFakingStatus(boolean newStatus) { public void setFakingStatus(boolean newStatus) {
fromNSAreCommingFakedExtendedBoluses = newStatus; fromNSAreCommingFakedExtendedBoluses = newStatus;
SP.putBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, fromNSAreCommingFakedExtendedBoluses); SP.putBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, fromNSAreCommingFakedExtendedBoluses);
} }
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
@ -118,62 +123,74 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
refreshConfiguration(); refreshConfiguration();
} }
@Override @Override
protected void onStop() { protected void onStop() {
MainApp.bus().unregister(this); MainApp.bus().unregister(this);
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventPreferenceChange s) { public void onStatusEvent(final EventPreferenceChange s) {
if (s.isChanged(R.string.key_virtualpump_type)) if (s.isChanged(R.string.key_virtualpump_type))
refreshConfiguration(); refreshConfiguration();
} }
@Override @Override
public boolean isFakingTempsByExtendedBoluses() { public boolean isFakingTempsByExtendedBoluses() {
return (Config.NSCLIENT) && fromNSAreCommingFakedExtendedBoluses; return (Config.NSCLIENT) && fromNSAreCommingFakedExtendedBoluses;
} }
@Override @Override
public PumpEnactResult loadTDDs() { public PumpEnactResult loadTDDs() {
//no result, could read DB in the future? // no result, could read DB in the future?
return new PumpEnactResult(); return new PumpEnactResult();
} }
@Override @Override
public boolean isInitialized() { public boolean isInitialized() {
return true; return true;
} }
@Override @Override
public boolean isSuspended() { public boolean isSuspended() {
return false; return false;
} }
@Override @Override
public boolean isBusy() { public boolean isBusy() {
return false; return false;
} }
@Override @Override
public boolean isConnected() { public boolean isConnected() {
return true; return true;
} }
@Override @Override
public boolean isConnecting() { public boolean isConnecting() {
return false; return false;
} }
@Override @Override
public boolean isHandshakeInProgress() { public boolean isHandshakeInProgress() {
return false; return false;
} }
@Override @Override
public void finishHandshaking() { public void finishHandshaking() {
} }
@Override @Override
public void connect(String reason) { public void connect(String reason) {
if (!Config.NSCLIENT) if (!Config.NSCLIENT)
@ -181,40 +198,48 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
lastDataTime = System.currentTimeMillis(); lastDataTime = System.currentTimeMillis();
} }
@Override @Override
public void disconnect(String reason) { public void disconnect(String reason) {
} }
@Override @Override
public void stopConnecting() { public void stopConnecting() {
} }
@Override @Override
public void getPumpStatus() { public void getPumpStatus() {
lastDataTime = System.currentTimeMillis(); lastDataTime = System.currentTimeMillis();
} }
@Override @Override
public PumpEnactResult setNewBasalProfile(Profile profile) { public PumpEnactResult setNewBasalProfile(Profile profile) {
lastDataTime = System.currentTimeMillis(); lastDataTime = System.currentTimeMillis();
// Do nothing here. we are using ConfigBuilderPlugin.getPlugin().getActiveProfile().getProfile(); // Do nothing here. we are using ConfigBuilderPlugin.getPlugin().getActiveProfile().getProfile();
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = true; result.success = true;
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok),
Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
return result; return result;
} }
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
return true; return true;
} }
@Override @Override
public long lastDataTime() { public long lastDataTime() {
return lastDataTime; return lastDataTime;
} }
@Override @Override
public double getBaseBasalRate() { public double getBaseBasalRate() {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ProfileFunctions.getInstance().getProfile();
@ -241,7 +266,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
SystemClock.sleep(200); SystemClock.sleep(200);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), delivering); bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), delivering);
bolusingEvent.percent = Math.min((int) (delivering / detailedBolusInfo.insulin * 100), 100); bolusingEvent.percent = Math.min((int)(delivering / detailedBolusInfo.insulin * 100), 100);
MainApp.bus().post(bolusingEvent); MainApp.bus().post(bolusingEvent);
delivering += 0.1d; delivering += 0.1d;
} }
@ -252,25 +277,26 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
MainApp.bus().post(bolusingEvent); MainApp.bus().post(bolusingEvent);
SystemClock.sleep(1000); SystemClock.sleep(1000);
if (L.isEnabled(L.PUMPCOMM)) if (L.isEnabled(L.PUMPCOMM))
log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result); log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: "
+ detailedBolusInfo.carbs + "g " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui()); MainApp.bus().post(new EventVirtualPumpUpdateGui());
lastDataTime = System.currentTimeMillis(); lastDataTime = System.currentTimeMillis();
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
return result; return result;
} }
@Override @Override
public void stopBolusDelivering() { public void stopBolusDelivering() {
} }
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
TemporaryBasal tempBasal = new TemporaryBasal() @Override
.date(System.currentTimeMillis()) public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
.absolute(absoluteRate) boolean enforceNew) {
.duration(durationInMinutes)
.source(Source.USER); TemporaryBasal tempBasal = new TemporaryBasal().date(System.currentTimeMillis()).absolute(absoluteRate)
.duration(durationInMinutes).source(Source.USER);
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = true; result.success = true;
result.enacted = true; result.enacted = true;
@ -286,13 +312,12 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
TemporaryBasal tempBasal = new TemporaryBasal() boolean enforceNew) {
.date(System.currentTimeMillis()) TemporaryBasal tempBasal = new TemporaryBasal().date(System.currentTimeMillis()).percent(percent)
.percent(percent) .duration(durationInMinutes).source(Source.USER);
.duration(durationInMinutes)
.source(Source.USER);
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = true; result.success = true;
result.enacted = true; result.enacted = true;
@ -309,17 +334,15 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
PumpEnactResult result = cancelExtendedBolus(); PumpEnactResult result = cancelExtendedBolus();
if (!result.success) if (!result.success)
return result; return result;
ExtendedBolus extendedBolus = new ExtendedBolus() ExtendedBolus extendedBolus = new ExtendedBolus().date(System.currentTimeMillis()).insulin(insulin)
.date(System.currentTimeMillis()) .durationInMinutes(durationInMinutes).source(Source.USER);
.insulin(insulin)
.durationInMinutes(durationInMinutes)
.source(Source.USER);
result.success = true; result.success = true;
result.enacted = true; result.enacted = true;
result.bolusDelivered = insulin; result.bolusDelivered = insulin;
@ -334,6 +357,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult cancelTempBasal(boolean force) { public PumpEnactResult cancelTempBasal(boolean force) {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -344,7 +368,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
result.enacted = true; result.enacted = true;
TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER); TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop); TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop);
//tempBasal = null; // tempBasal = null;
if (L.isEnabled(L.PUMPCOMM)) if (L.isEnabled(L.PUMPCOMM))
log.debug("Canceling temp basal: " + result); log.debug("Canceling temp basal: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui()); MainApp.bus().post(new EventVirtualPumpUpdateGui());
@ -353,6 +377,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public PumpEnactResult cancelExtendedBolus() { public PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -372,6 +397,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return result; return result;
} }
@Override @Override
public JSONObject getJSONStatus(Profile profile, String profileName) { public JSONObject getJSONStatus(Profile profile, String profileName) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -415,21 +441,25 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
return pump; return pump;
} }
@Override @Override
public String deviceID() { public String deviceID() {
return "VirtualPump"; return "VirtualPump";
} }
@Override @Override
public PumpDescription getPumpDescription() { public PumpDescription getPumpDescription() {
return pumpDescription; return pumpDescription;
} }
@Override @Override
public String shortStatus(boolean veryShort) { public String shortStatus(boolean veryShort) {
return "Virtual Pump"; return "Virtual Pump";
} }
public PumpType getPumpType() { public PumpType getPumpType() {
return pumpType; return pumpType;
} }
@ -455,4 +485,15 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
} }
@Override
public List<CustomAction> getCustomActions() {
return null;
}
@Override
public PumpEnactResult executeCustomAction(CustomActionType customActionType) {
return null;
}
} }

View file

@ -29,15 +29,15 @@ import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
RecyclerView recyclerView; RecyclerView recyclerView;
LinearLayoutManager llm; LinearLayoutManager llm;
@ -49,16 +49,20 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
Intervals<TemporaryBasal> tempBasalList; Intervals<TemporaryBasal> tempBasalList;
RecyclerViewAdapter(Intervals<TemporaryBasal> tempBasalList) { RecyclerViewAdapter(Intervals<TemporaryBasal> tempBasalList) {
this.tempBasalList = tempBasalList; this.tempBasalList = tempBasalList;
} }
@Override @Override
public TempBasalsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { public TempBasalsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_tempbasals_item, viewGroup, false); View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_tempbasals_item,
viewGroup, false);
return new TempBasalsViewHolder(v); return new TempBasalsViewHolder(v);
} }
@Override @Override
public void onBindViewHolder(TempBasalsViewHolder holder, int position) { public void onBindViewHolder(TempBasalsViewHolder holder, int position) {
TemporaryBasal tempBasal = tempBasalList.getReversed(position); TemporaryBasal tempBasal = tempBasalList.getReversed(position);
@ -87,7 +91,8 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
if (tempBasal.isAbsolute) { if (tempBasal.isAbsolute) {
Profile profile = ProfileFunctions.getInstance().getProfile(tempBasal.date); Profile profile = ProfileFunctions.getInstance().getProfile(tempBasal.date);
if (profile != null) { if (profile != null) {
holder.absolute.setText(DecimalFormatter.to0Decimal(tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile), " U/h")); holder.absolute.setText(DecimalFormatter.to2Decimal(
tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile), " U/h"));
holder.percent.setText(""); holder.percent.setText("");
} else { } else {
holder.absolute.setText(MainApp.gs(R.string.noprofile)); holder.absolute.setText(MainApp.gs(R.string.noprofile));
@ -115,17 +120,20 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
holder.remove.setTag(tempBasal); holder.remove.setTag(tempBasal);
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return tempBasalList.size(); return tempBasalList.size();
} }
@Override @Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) { public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView); super.onAttachedToRecyclerView(recyclerView);
} }
public class TempBasalsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public class TempBasalsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv; CardView cv;
TextView date; TextView date;
TextView duration; TextView duration;
@ -140,33 +148,36 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
TextView ph; TextView ph;
TextView ns; TextView ns;
TempBasalsViewHolder(View itemView) { TempBasalsViewHolder(View itemView) {
super(itemView); super(itemView);
cv = (CardView) itemView.findViewById(R.id.tempbasals_cardview); cv = (CardView)itemView.findViewById(R.id.tempbasals_cardview);
date = (TextView) itemView.findViewById(R.id.tempbasals_date); date = (TextView)itemView.findViewById(R.id.tempbasals_date);
duration = (TextView) itemView.findViewById(R.id.tempbasals_duration); duration = (TextView)itemView.findViewById(R.id.tempbasals_duration);
absolute = (TextView) itemView.findViewById(R.id.tempbasals_absolute); absolute = (TextView)itemView.findViewById(R.id.tempbasals_absolute);
percent = (TextView) itemView.findViewById(R.id.tempbasals_percent); percent = (TextView)itemView.findViewById(R.id.tempbasals_percent);
realDuration = (TextView) itemView.findViewById(R.id.tempbasals_realduration); realDuration = (TextView)itemView.findViewById(R.id.tempbasals_realduration);
netRatio = (TextView) itemView.findViewById(R.id.tempbasals_netratio); netRatio = (TextView)itemView.findViewById(R.id.tempbasals_netratio);
netInsulin = (TextView) itemView.findViewById(R.id.tempbasals_netinsulin); netInsulin = (TextView)itemView.findViewById(R.id.tempbasals_netinsulin);
iob = (TextView) itemView.findViewById(R.id.tempbasals_iob); iob = (TextView)itemView.findViewById(R.id.tempbasals_iob);
extendedFlag = (TextView) itemView.findViewById(R.id.tempbasals_extendedflag); extendedFlag = (TextView)itemView.findViewById(R.id.tempbasals_extendedflag);
ph = (TextView) itemView.findViewById(R.id.pump_sign); ph = (TextView)itemView.findViewById(R.id.pump_sign);
ns = (TextView) itemView.findViewById(R.id.ns_sign); ns = (TextView)itemView.findViewById(R.id.ns_sign);
remove = (TextView) itemView.findViewById(R.id.tempbasals_remove); remove = (TextView)itemView.findViewById(R.id.tempbasals_remove);
remove.setOnClickListener(this); remove.setOnClickListener(this);
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
} }
@Override @Override
public void onClick(View v) { public void onClick(View v) {
final TemporaryBasal tempBasal = (TemporaryBasal) v.getTag(); final TemporaryBasal tempBasal = (TemporaryBasal)v.getTag();
switch (v.getId()) { switch (v.getId()) {
case R.id.tempbasals_remove: case R.id.tempbasals_remove:
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(tempBasal.date)); builder.setMessage(MainApp.gs(R.string.removerecord) + "\n"
+ DateUtil.dateAndTimeString(tempBasal.date));
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
final String _id = tempBasal._id; final String _id = tempBasal._id;
if (NSUpload.isIdValid(_id)) { if (NSUpload.isIdValid(_id)) {
@ -185,20 +196,21 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
} }
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.treatments_tempbasals_fragment, container, false); View view = inflater.inflate(R.layout.treatments_tempbasals_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.tempbasals_recyclerview); recyclerView = (RecyclerView)view.findViewById(R.id.tempbasals_recyclerview);
recyclerView.setHasFixedSize(true); recyclerView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext()); llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm); recyclerView.setLayoutManager(llm);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTemporaryBasalsFromHistory()); RecyclerViewAdapter adapter = new RecyclerViewAdapter(TreatmentsPlugin.getPlugin()
.getTemporaryBasalsFromHistory());
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
tempBasalTotalView = (TextView) view.findViewById(R.id.tempbasals_totaltempiob); tempBasalTotalView = (TextView)view.findViewById(R.id.tempbasals_totaltempiob);
context = getContext(); context = getContext();
@ -206,22 +218,26 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment {
return view; return view;
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventTempBasalChange ignored) { public void onStatusEvent(final EventTempBasalChange ignored) {
updateGUI(); updateGUI();
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventNewBG ignored) { public void onStatusEvent(final EventNewBG ignored) {
updateGUI(); updateGUI();
} }
@Override @Override
protected void updateGUI() { protected void updateGUI() {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTemporaryBasalsFromHistory()), false); recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin()
.getTemporaryBasalsFromHistory()), false);
IobTotal tempBasalsCalculation = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals(); IobTotal tempBasalsCalculation = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals();
if (tempBasalsCalculation != null) if (tempBasalsCalculation != null)
tempBasalTotalView.setText(DecimalFormatter.to2Decimal(tempBasalsCalculation.basaliob, " U")); tempBasalTotalView.setText(DecimalFormatter.to2Decimal(tempBasalsCalculation.basaliob, " U"));

View file

@ -1,20 +1,58 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import static org.powermock.api.mockito.PowerMockito.when;
import junit.framework.Assert; import junit.framework.Assert;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.SPMocker;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
import info.nightscout.utils.T;
/** /**
* Created by andy on 6/16/18. * Created by andy on 6/16/18.
*/ */
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MainApp.class, DatabaseHelper.class, DateUtil.class, SP.class })
public class BasalProfileUTest { public class BasalProfileUTest {
// MainApp mainApp = new MainApp();
@Before
public void initMocking() {
AAPSMocker.mockMainApp();
AAPSMocker.mockStrings();
AAPSMocker.mockDatabaseHelper();
SPMocker.prepareMock();
PowerMockito.mockStatic(DateUtil.class);
when(DateUtil.now()).thenReturn(1514766900000L + T.mins(1).msecs());
}
@Test @Test
public void getProfilesByHour() throws Exception { public void getProfilesByHour() throws Exception {
MedtronicUtil.setPumpStatus(new MedtronicPumpStatus(new PumpDescription()));
MedtronicUtil.getPumpStatus().pumpType = PumpType.Medtronic_522_722;
PumpType pumpType = MedtronicUtil.getPumpStatus().pumpType;
BasalProfile basalProfile = new BasalProfile(); BasalProfile basalProfile = new BasalProfile();
byte[] data = { // byte[] data = { //
0x48, 0x00, 0x00, 0x40, 0x00, 0x02, 0x38, 0x00, 0x04, 0x3A, 0x00, 0x06, 0x32, 0x00, 0x0C, 0x26, 0x00, // 0x48, 0x00, 0x00, 0x40, 0x00, 0x02, 0x38, 0x00, 0x04, 0x3A, 0x00, 0x06, 0x32, 0x00, 0x0C, 0x26, 0x00, //

View file

@ -24,6 +24,13 @@ CGMS [not in plan for now]:
AAPS-Medtronic AAPS-Medtronic
============== ==============
- ? history: TDD query
history retrive doesn't show whats happening
datetime parsimg problem
Invalid entry:
Entry: EndResultTotals = [0x07 0x00 0x00 0x05 0xFA 0xBF 0x12] PumpHistoryRecord [type=EndResultTotals [7 , 0x07], DT: x , length=5,2,0(7), head=00 00 05 FA , datetime=BF 12 , rawData=07 00 00 05 FA BF 12 ]
- history: - integrate - history: - integrate
- basal change code - basal change code
@ -126,4 +133,62 @@ Bugs:
+ TBR (554) ? + TBR (554) ?
+ Remaining Insulin [554] + Remaining Insulin [554]
+ Get Basal profile returns just part of profile + Get Basal profile returns just part of profile
+ Set TBR problem (after Bolus fixes) + Set TBR problem (after Bolus fixes)
========================================================================================================
None(0, "None", 1, 0, 0), // Bolus(0x01, "Bolus", 4, 5, 4), // 4,5,0 -> 4,5,4 Bolus(0x01, "Bolus", 2, 5, 4),
// Thear
Bolus(0x01, "Bolus", 4, DateFormat.LongDate, 0), // 523+[H=8]
TempBasalRate(0x33, "TempBasal", 2, 5, 1), //
TempBasalDuration(0x16, "TempBasalDuration"), //
// Status changes
Prime(0x03, "Prime", 5, 5, 0), //
PumpSuspend(0x1e, "PumpSuspend"), //
PumpResume(0x1f, "PumpResume"), //
Rewind(0x21, "Rewind"), //
// time change
ChangeTime(0x17, "ChangeTime"), //
NewTimeSet(0x18, "NewTimeSet"), //
// settings
ClearSettings(0x22, "ClearSettings"), // 8?
SaveSettings(0x5d), //
SelectBasalProfile(0x14, "SelectBasalProfile"), //
ChangeMaxBolus(0x24), // 8?
ChangeMaxBasal(0x2c), //
ChangeTempBasalType((byte)0x62), // ChangeTempBasalTypePumpEvent
// basal profile
//ChangeBasalProfile_OldProfile(0x08, 2, 5, 145), // // V1: 2,5,42 V2:2,5,145; V4: V5
ChangeBasalProfile_NewProfile(0x09, 2, 5, 145), //
// Daily Totals
DailyTotals512(0x6c, "Daily Totals 512", 0, 0, 36), //
DailyTotals522(0x6d, "Daily Totals 522", 1, 2, 41), // // hack1(0x6d, "hack1", 46, 5, 0),
DailyTotals523(0x6e, "Daily Totals 523", 1, 2, 49), // 1102014-03-17T00:00:00
ChangeVariableBolus(0x5e), //
EndResultTotals(0x07, "ResultTotals", 5, 2, 0), // V1: 5/5/41 V2: 5,2,3 V3, 5,2,0 V5: 7/10(523)
BasalProfileStart(0x7b, 2, 5, 3), // // 722