More sync prototyping.

This commit is contained in:
Johannes Mockenhaupt 2017-10-20 18:51:15 +02:00
parent 1aa2ce48a1
commit 87c1c4b112
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
3 changed files with 167 additions and 75 deletions

View file

@ -101,24 +101,19 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
@Override @Override
public void run() { public void run() {
ComboPlugin plugin = ComboPlugin.getPlugin(); ComboPlugin plugin = ComboPlugin.getPlugin();
// status if (plugin.isInitialized()) {
if (plugin.getPump().lastCmdResult == null) { // status
statusView.setText("Initializing");
} else {
statusView.setText(plugin.getPump().state.getStateSummary()); statusView.setText(plugin.getPump().state.getStateSummary());
} if (plugin.getPump().state.errorMsg != null) {
if (plugin.getPump().state.errorMsg != null) { statusView.setTextColor(Color.RED);
statusView.setTextColor(Color.RED); } else if (plugin.getPump().state.suspended) {
} else if (plugin.getPump().state.suspended) { statusView.setTextColor(Color.YELLOW);
statusView.setTextColor(Color.YELLOW); } else {
} else { statusView.setTextColor(Color.WHITE);
statusView.setTextColor(Color.WHITE); }
}
CommandResult lastCmdResult = plugin.getPump().lastCmdResult;
if (plugin.isInitialized() && lastCmdResult != null) {
PumpState ps = plugin.getPump().state;
// battery // battery
PumpState ps = plugin.getPump().state;
if (ps.batteryState == PumpState.EMPTY) { if (ps.batteryState == PumpState.EMPTY) {
batteryView.setText("{fa-battery-empty}"); batteryView.setText("{fa-battery-empty}");
batteryView.setTextColor(Color.RED); batteryView.setTextColor(Color.RED);
@ -131,6 +126,8 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
} }
// reservoir // reservoir
int reservoirLevel = plugin.getPump().reservoirLevel;
reservoirView.setText(reservoirLevel == -1 ? "" : "" + reservoirLevel + " U");
if (ps.insulinState == PumpState.LOW) { if (ps.insulinState == PumpState.LOW) {
reservoirView.setTextColor(Color.YELLOW); reservoirView.setTextColor(Color.YELLOW);
} else if (ps.insulinState == PumpState.EMPTY) { } else if (ps.insulinState == PumpState.EMPTY) {
@ -138,35 +135,38 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
} else { } else {
reservoirView.setTextColor(Color.WHITE); reservoirView.setTextColor(Color.WHITE);
} }
int reservoirLevel = plugin.getPump().reservoirLevel;
reservoirView.setText(reservoirLevel == -1 ? "" : "" + reservoirLevel + " U");
// last connection // last connection
String minAgo = DateUtil.minAgo(lastCmdResult.completionTime); CommandResult lastCmdResult = plugin.getPump().lastCmdResult;
String time = DateUtil.timeString(lastCmdResult.completionTime); if (lastCmdResult != null) {
lastConnectionView.setText("" + minAgo + " (" + time + ")"); String minAgo = DateUtil.minAgo(lastCmdResult.completionTime);
String time = DateUtil.timeString(lastCmdResult.completionTime);
lastConnectionView.setText("" + minAgo + " (" + time + ")");
// last bolus // last bolus
plugin.getPump().history.bolusHistory.add(new Bolus(System.currentTimeMillis() - 7 * 60 * 1000, 12.8d)); plugin.getPump().history.bolusHistory.add(new Bolus(System.currentTimeMillis() - 7 * 60 * 1000, 12.8d));
Bolus bolus = plugin.getPump().lastBolus; Bolus bolus = plugin.getPump().lastBolus;
if (bolus == null || bolus.timestamp + 6 * 60 * 60 * 1000 < System.currentTimeMillis()) { if (bolus == null || bolus.timestamp + 6 * 60 * 60 * 1000 < System.currentTimeMillis()) {
lastBolusView.setText(""); lastBolusView.setText("");
} else { } else {
long agoMsc = System.currentTimeMillis() - bolus.timestamp; long agoMsc = System.currentTimeMillis() - bolus.timestamp;
double agoHours = agoMsc / 60d / 60d / 1000d; double agoHours = agoMsc / 60d / 60d / 1000d;
lastBolusView.setText(DecimalFormatter.to2Decimal(bolus.amount) + " U " + lastBolusView.setText(DecimalFormatter.to2Decimal(bolus.amount) + " U " +
"(" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ", " "(" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ", "
+ DateUtil.timeString(bolus.timestamp) + ") "); + DateUtil.timeString(bolus.timestamp) + ") ");
} }
// TBR // TBR
boolean tbrActive = ps.tbrPercent != -1 && ps.tbrPercent != 100; boolean tbrActive = ps.tbrPercent != -1 && ps.tbrPercent != 100;
if (tbrActive) { String tbrStr = "";
long minSinceRead = (System.currentTimeMillis() - lastCmdResult.completionTime) / 1000 / 60; if (tbrActive) {
String tbr = ps.tbrPercent + "% (" + (ps.tbrRemainingDuration - minSinceRead) + " min remaining)"; long minSinceRead = (System.currentTimeMillis() - lastCmdResult.completionTime) / 1000 / 60;
tempBasalText.setText(tbr); long remaining = ps.tbrRemainingDuration - minSinceRead;
} else { if (remaining >= 0) {
tempBasalText.setText(""); tbrStr = ps.tbrPercent + "% (" + remaining + " min remaining)";
}
}
tempBasalText.setText(tbrStr);
} }
} }
} }

View file

@ -13,7 +13,9 @@ import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List;
import de.jotomo.ruffy.spi.BolusProgressReporter; import de.jotomo.ruffy.spi.BolusProgressReporter;
import de.jotomo.ruffy.spi.CommandResult; import de.jotomo.ruffy.spi.CommandResult;
@ -21,6 +23,7 @@ import de.jotomo.ruffy.spi.PumpState;
import de.jotomo.ruffy.spi.RuffyCommands; import de.jotomo.ruffy.spi.RuffyCommands;
import de.jotomo.ruffy.spi.history.Bolus; import de.jotomo.ruffy.spi.history.Bolus;
import de.jotomo.ruffy.spi.history.PumpHistoryRequest; import de.jotomo.ruffy.spi.history.PumpHistoryRequest;
import de.jotomo.ruffy.spi.history.Tbr;
import de.jotomo.ruffyscripter.RuffyCommandsV1Impl; import de.jotomo.ruffyscripter.RuffyCommandsV1Impl;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -30,6 +33,7 @@ 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.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
@ -263,7 +267,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@Override @Override
public void initialize() { public void initialize() {
runCommand("Syncing pump state", new CommandExecution() { CommandResult commandResult = runCommand("Syncing pump state", new CommandExecution() {
@Override @Override
public CommandResult execute() { public CommandResult execute() {
return ruffyScripter.readHistory( return ruffyScripter.readHistory(
@ -271,11 +275,59 @@ public class ComboPlugin implements PluginBase, PumpInterface {
.reservoirLevel(true) .reservoirLevel(true)
.bolusHistory(PumpHistoryRequest.LAST) .bolusHistory(PumpHistoryRequest.LAST)
.tbrHistory(PumpHistoryRequest.LAST) .tbrHistory(PumpHistoryRequest.LAST)
.errorHistory(PumpHistoryRequest.LAST) .errorHistory(PumpHistoryRequest.LAST));
.tddHistory(PumpHistoryRequest.LAST));
} }
}); });
boolean syncNeeded = false;
// last bolus
List<Treatment> treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory();
Collections.reverse(treatments);
Treatment aapsBolus = null;
for (Treatment t : treatments) {
if (t.insulin != 0) {
aapsBolus = t;
break;
}
}
Bolus pumpBolus = null;
List<Bolus> bolusHistory = commandResult.history.bolusHistory;
if (!bolusHistory.isEmpty()) {
pumpBolus = bolusHistory.get(0);
}
if (aapsBolus == null || pumpBolus == null) {
syncNeeded = true;
} else if (Math.abs(aapsBolus.insulin - pumpBolus.amount) > 0.05
|| aapsBolus.date != pumpBolus.timestamp) {
syncNeeded = true;
}
// last tbr
List<TemporaryBasal> tempBasals = MainApp.getConfigBuilder().getTemporaryBasalsFromHistory().getReversedList();
TemporaryBasal aapsTbr = null;
if (!tempBasals.isEmpty()) {
aapsTbr = tempBasals.get(0);
}
Tbr pumpTbr = null;
List<Tbr> tbrHistory = commandResult.history.tbrHistory;
if(!tbrHistory.isEmpty()) {
pumpTbr = tbrHistory.get(0);
}
if (aapsTbr == null || pumpTbr == null) {
syncNeeded = true;
} else if (aapsTbr.percentRate != pumpTbr.percent || aapsTbr.durationInMinutes != pumpTbr.duration) {
syncNeeded = true;
}
// last error
// TODO add DB table
if (syncNeeded) {
runFullSync();
}
// TODO // TODO
// detectStateMismatch(): expensive sync, checking everything (detectTbrMisMatch us called for every command) // detectStateMismatch(): expensive sync, checking everything (detectTbrMisMatch us called for every command)
// check 'lasts' of pump against treatment db, request full sync if needed // check 'lasts' of pump against treatment db, request full sync if needed
@ -304,12 +356,12 @@ public class ComboPlugin implements PluginBase, PumpInterface {
// if (notAUserRequest && wasRunAtLeastOnce && ranWithinTheLastMinute) { // if (notAUserRequest && wasRunAtLeastOnce && ranWithinTheLastMinute) {
// log.debug("Not fetching state from pump, since we did already within the last 60 seconds"); // log.debug("Not fetching state from pump, since we did already within the last 60 seconds");
// } else { // } else {
runCommand("Refreshing", new CommandExecution() { runCommand("Refreshing", new CommandExecution() {
@Override @Override
public CommandResult execute() { public CommandResult execute() {
return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true).bolusHistory(PumpHistoryRequest.LAST)); return ruffyScripter.readHistory(new PumpHistoryRequest().reservoirLevel(true).bolusHistory(PumpHistoryRequest.LAST));
} }
}); });
// } // }
} }
@ -601,29 +653,9 @@ public class ComboPlugin implements PluginBase, PumpInterface {
pump.lastCmdResult = commandResult; pump.lastCmdResult = commandResult;
pump.state = commandResult.state; pump.state = commandResult.state;
// detectTbrMismatch(): 'quick' check with not overhead on the pump side // TODO are there cases when this check should NOT be performed? perform this explicitly or have a flag to skip this?
// TODO check if this works with pump suspend, esp. around pump suspend there'll be syncing to do; checkForTbrMismatch();
TemporaryBasal aapsTbr = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
if (aapsTbr == null && pump.state.tbrActive) {
// pump runs TBR AAPS is unaware off
// => fetch full history so the full TBR is added to treatments
} else if (aapsTbr != null && !pump.state.tbrActive) {
// AAPS has a TBR but the pump isn't running a TBR
// => remove the TBR from treatments
// => fetch full history, so that if the TBR was cancelled but ran some time we get the IOB from that partial TBR
} else if (aapsTbr != null && pump.state.tbrActive) {
// both AAPS and pump have a TBR ...
if (aapsTbr.percentRate != pump.state.tbrPercent) {
// ... but they have different percentages
// => remove TBR from treatments
// => full history sync so we get up to date on actual IOB
}
int durationDiff = Math.abs(aapsTbr.getPlannedRemainingMinutes() - pump.state.tbrRemainingDuration);
if (durationDiff > 2) {
// ... but they have different runtimes
// ^ same as above, merge branches
}
}
// TODO not propely set all the time ... // TODO not propely set all the time ...
if (pump.lastCmdResult == null) { if (pump.lastCmdResult == null) {
@ -648,6 +680,66 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return commandResult; return commandResult;
} }
private void checkForTbrMismatch() {
// detectTbrMismatch(): 'quick' check with not overhead on the pump side
// TODO check if this works with pump suspend, esp. around pump suspend there'll be syncing to do;
TemporaryBasal aapsTbr = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
if (aapsTbr == null && pump.state.tbrActive) {
// pump runs TBR AAPS is unaware off
// => fetch full history so the full TBR is added to treatments
log.debug("JOE: sync required 1");
runFullSync();
} else if (aapsTbr != null && !pump.state.tbrActive) {
// AAPS has a TBR but the pump isn't running a TBR
// => remove the TBR from treatments
// => fetch full history, so that if the TBR was cancelled but ran some time we get the IOB from that partial TBR
log.debug("JOE: sync required 2");
MainApp.getDbHelper().delete(aapsTbr);
runFullSync();
} else if (aapsTbr != null && pump.state.tbrActive) {
// both AAPS and pump have a TBR ...
if (aapsTbr.percentRate != pump.state.tbrPercent) {
// ... but they have different percentages
// => remove TBR from treatments
// => full history sync so we get up to date on actual IOB
log.debug("JOE: sync required 3");
MainApp.getDbHelper().delete(aapsTbr);
runFullSync();
}
int durationDiff = Math.abs(aapsTbr.getPlannedRemainingMinutes() - pump.state.tbrRemainingDuration);
if (durationDiff > 2) {
// ... but they have different runtimes
// ^ same as above, merge branches
log.debug("JOE: sync required 4");
MainApp.getDbHelper().delete(aapsTbr);
runFullSync();
}
}
// TODO request a loop run to (re)apply a TBR/SMB given this new information? or just wait till next iteration?
// could take 15m or so if there are missed SGVs ...
}
private void runFullSync() {
CommandResult commandResult = runCommand("Syncing full pump history", new CommandExecution() {
@Override
public CommandResult execute() {
return ruffyScripter.readHistory(
new PumpHistoryRequest()
.reservoirLevel(true)
.bolusHistory(PumpHistoryRequest.FULL)
.tbrHistory(PumpHistoryRequest.FULL)
.errorHistory(PumpHistoryRequest.FULL)
.tddHistory(PumpHistoryRequest.FULL)
);
}
});
}
@Override @Override
public PumpEnactResult cancelExtendedBolus() { public PumpEnactResult cancelExtendedBolus() {
return OPERATION_NOT_SUPPORTED; return OPERATION_NOT_SUPPORTED;

View file

@ -77,10 +77,10 @@ public class PumpState {
} }
public String getStateSummary() { public String getStateSummary() {
if (suspended) if (errorMsg != null)
return "Suspended";
else if (errorMsg != null)
return errorMsg; return errorMsg;
else if (suspended)
return "Suspended";
return "Running"; return "Running";
} }