Initial bolus syncing.
This commit is contained in:
parent
744d24cbcf
commit
8d3947dc7f
3 changed files with 147 additions and 88 deletions
|
@ -7,7 +7,6 @@ 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 java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -26,10 +25,13 @@ import info.nightscout.androidaps.R;
|
||||||
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.db.CareportalEvent;
|
||||||
|
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||||
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.db.Treatment;
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||||
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;
|
||||||
|
@ -236,91 +238,23 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult result = runCommand("Refreshing", 3, ruffyScripter::readReservoirLevelAndLastBolus);
|
CommandResult result = runCommand("Refreshing", 3, ruffyScripter::readReservoirLevelAndLastBolus);
|
||||||
if (result.reservoirLevel != PumpState.UNKNOWN)
|
updateLocalData(result);
|
||||||
pump.reservoirLevel = result.reservoirLevel;
|
|
||||||
pump.state = result.state;
|
|
||||||
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
|
||||||
|
|
||||||
// TODO fuse the below into 'sync'? or make checkForTbrMismatch jut a trigger to issue a sync if needed; don't run sync twice as is nice
|
// TODO fuse the below into 'sync'? or make checkForTbrMismatch jut a trigger to issue a sync if needed; don't run sync twice as is nice
|
||||||
// checkForTbrMismatch();
|
// checkForTbrMismatch();
|
||||||
// checkPumpHistory();
|
checkPumpHistory();
|
||||||
// checkPumpDate()
|
// checkPumpDate()
|
||||||
|
|
||||||
pump.initialized = true;
|
pump.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void updateLocalData(CommandResult result) {
|
||||||
* Checks if there are any changes on the pump AAPS isn't aware of yet and if so, read the
|
if (result.reservoirLevel != PumpState.UNKNOWN)
|
||||||
* full pump history and update AAPS' DB.
|
pump.reservoirLevel = result.reservoirLevel;
|
||||||
*/
|
if (result.lastBolus != null)
|
||||||
private void checkPumpHistory() {
|
pump.lastBolus = result.lastBolus;
|
||||||
CommandResult commandResult = runCommand(MainApp.sResources.getString(R.string.combo_pump_action_checking_history), 3, () ->
|
pump.state = result.state;
|
||||||
ruffyScripter.readHistory(
|
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||||
new PumpHistoryRequest()
|
|
||||||
.bolusHistory(PumpHistoryRequest.LAST)
|
|
||||||
.tbrHistory(PumpHistoryRequest.LAST)
|
|
||||||
.errorHistory(PumpHistoryRequest.LAST)));
|
|
||||||
|
|
||||||
if (!commandResult.success || commandResult.history == null) {
|
|
||||||
// TODO error case, command
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO opt, construct PumpHistoryRequest to requset only what needs updating
|
|
||||||
boolean syncNeeded = false;
|
|
||||||
PumpHistoryRequest request = new PumpHistoryRequest();
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|| (Math.abs(aapsBolus.insulin - pumpBolus.amount) > 0.05 || aapsBolus.date != pumpBolus.timestamp)) {
|
|
||||||
syncNeeded = true;
|
|
||||||
request.bolusHistory = PumpHistoryRequest.FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|| (aapsTbr.percentRate != pumpTbr.percent || aapsTbr.durationInMinutes != pumpTbr.duration)) {
|
|
||||||
syncNeeded = true;
|
|
||||||
request.tbrHistory = PumpHistoryRequest.FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// last error
|
|
||||||
// TODO add DB table ... or just keep in memory? does android allow that (fragment kill frenzy) without workarounds?
|
|
||||||
// is comboplugin a service or a class with statics?
|
|
||||||
request.pumpErrorHistory = PumpHistoryRequest.FULL;
|
|
||||||
|
|
||||||
// tdd
|
|
||||||
// TODO; ... just fetch them on-deamand when the user opens the fragment?
|
|
||||||
|
|
||||||
|
|
||||||
if (syncNeeded) {
|
|
||||||
runFullSync(request);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO uses profile values for the time being
|
// TODO uses profile values for the time being
|
||||||
|
@ -439,11 +373,11 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify we're update to date and know the most recent bolus
|
// verify we're update to date and know the most recent bolus
|
||||||
|
// TODO should we check against pump.lastBolus or rather the DB ...
|
||||||
if (!Objects.equals(pump.lastBolus, reservoirBolusResult.lastBolus)) {
|
if (!Objects.equals(pump.lastBolus, reservoirBolusResult.lastBolus)) {
|
||||||
// TODO needs syncing with DB first
|
new Thread(this::checkPumpHistory).start();
|
||||||
// new Thread(this::checkPumpHistory).start();
|
return new PumpEnactResult().success(false).enacted(false).
|
||||||
// return new PumpEnactResult().success(false).enacted(false).
|
comment(MainApp.sResources.getString(R.string.combo_pump_bolus_history_state_mismatch));
|
||||||
// comment(MainApp.sResources.getString(R.string.combo_pump_bolus_history_state_mismatch));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancelBolus) {
|
if (cancelBolus) {
|
||||||
|
@ -476,6 +410,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
if (cancelBolus) {
|
if (cancelBolus) {
|
||||||
// if cancellation was requested, the delivered bolus is allowed to differ from requested
|
// if cancellation was requested, the delivered bolus is allowed to differ from requested
|
||||||
} else if (lastPumpBolus == null || lastPumpBolus.amount != detailedBolusInfo.insulin) {
|
} else if (lastPumpBolus == null || lastPumpBolus.amount != detailedBolusInfo.insulin) {
|
||||||
|
// TODO schedule forced history sync
|
||||||
return new PumpEnactResult().success(false).enacted(false).
|
return new PumpEnactResult().success(false).enacted(false).
|
||||||
comment(MainApp.sResources.getString(R.string.combo_pump_bolus_verification_failed));
|
comment(MainApp.sResources.getString(R.string.combo_pump_bolus_verification_failed));
|
||||||
}
|
}
|
||||||
|
@ -559,7 +494,6 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
PumpState state = commandResult.state;
|
PumpState state = commandResult.state;
|
||||||
if (state.tbrActive && state.tbrPercent == percent
|
if (state.tbrActive && state.tbrPercent == percent
|
||||||
&& (state.tbrRemainingDuration == durationInMinutes || state.tbrRemainingDuration == durationInMinutes - 1)) {
|
&& (state.tbrRemainingDuration == durationInMinutes || state.tbrRemainingDuration == durationInMinutes - 1)) {
|
||||||
pump.tbrSetTime = state.timestamp;
|
|
||||||
TemporaryBasal tempStart = new TemporaryBasal(state.timestamp);
|
TemporaryBasal tempStart = new TemporaryBasal(state.timestamp);
|
||||||
// TODO commandResult.state.tbrRemainingDuration might already display 29 if 30 was set, since 29:59 is shown as 29 ...
|
// TODO commandResult.state.tbrRemainingDuration might already display 29 if 30 was set, since 29:59 is shown as 29 ...
|
||||||
// we should check this, but really ... something must be really screwed up if that number was anything different
|
// we should check this, but really ... something must be really screwed up if that number was anything different
|
||||||
|
@ -571,6 +505,10 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
tempStart.source = Source.USER;
|
tempStart.source = Source.USER;
|
||||||
ConfigBuilderPlugin treatmentsInterface = MainApp.getConfigBuilder();
|
ConfigBuilderPlugin treatmentsInterface = MainApp.getConfigBuilder();
|
||||||
treatmentsInterface.addToHistoryTempBasal(tempStart);
|
treatmentsInterface.addToHistoryTempBasal(tempStart);
|
||||||
|
|
||||||
|
pump.state = commandResult.state;
|
||||||
|
pump.tbrSetTime = state.timestamp;
|
||||||
|
MainApp.bus().post(new EventComboPumpUpdateGUI());
|
||||||
}
|
}
|
||||||
|
|
||||||
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
PumpEnactResult pumpEnactResult = new PumpEnactResult();
|
||||||
|
@ -649,7 +587,7 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
return pumpEnactResult;
|
return pumpEnactResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CommandExecution {
|
private interface CommandExecution {
|
||||||
CommandResult execute();
|
CommandResult execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,16 +675,116 @@ public class ComboPlugin implements PluginBase, PumpInterface {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runFullSync(final PumpHistoryRequest request) {
|
/**
|
||||||
CommandResult result = runCommand("Syncing full pump history", 3, () -> ruffyScripter.readHistory(request));
|
* Checks if there are any changes on the pump AAPS isn't aware of yet and if so, read the
|
||||||
|
* full pump history and update AAPS' DB.
|
||||||
|
*/
|
||||||
|
private boolean checkPumpHistory() {
|
||||||
|
CommandResult commandResult = runCommand(MainApp.sResources.getString(R.string.combo_pump_action_checking_history), 3, () ->
|
||||||
|
ruffyScripter.readHistory(
|
||||||
|
new PumpHistoryRequest()
|
||||||
|
.bolusHistory(PumpHistoryRequest.LAST)
|
||||||
|
.tbrHistory(PumpHistoryRequest.LAST)
|
||||||
|
.errorHistory(PumpHistoryRequest.LAST)));
|
||||||
|
|
||||||
|
if (!commandResult.success || commandResult.history == null) {
|
||||||
|
// TODO error case, command
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO opt, construct PumpHistoryRequest to requset only what needs updating
|
||||||
|
boolean syncNeeded = false;
|
||||||
|
PumpHistoryRequest request = new PumpHistoryRequest();
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|| (Math.abs(aapsBolus.insulin - pumpBolus.amount) > 0.05 || aapsBolus.date != pumpBolus.timestamp)) {
|
||||||
|
log.debug("Last bolus on pump is unknown, refreshing full bolus history");
|
||||||
|
syncNeeded = true;
|
||||||
|
request.bolusHistory = PumpHistoryRequest.FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|| (aapsTbr.percentRate != pumpTbr.percent || aapsTbr.durationInMinutes != pumpTbr.duration)) {
|
||||||
|
// TODO
|
||||||
|
// log.debug("Last TBR on pump is unknown, refreshing full TBR history");
|
||||||
|
// syncNeeded = true;
|
||||||
|
// request.tbrHistory = PumpHistoryRequest.FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// last error
|
||||||
|
// TODO add DB table ... or just keep in memory? does android allow that (fragment kill frenzy) without workarounds?
|
||||||
|
// is comboplugin a service or a class with statics?
|
||||||
|
// request.pumpErrorHistory = PumpHistoryRequest.FULL;
|
||||||
|
|
||||||
|
// tdd
|
||||||
|
// TODO; ... just fetch them on-deamand when the user opens the fragment?
|
||||||
|
|
||||||
|
|
||||||
|
if (syncNeeded) {
|
||||||
|
runFullSync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runFullSync(final PumpHistoryRequest request) {
|
||||||
|
CommandResult result = runCommand("Syncing pump history", 3, () -> ruffyScripter.readHistory(request));
|
||||||
|
if (!result.success) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseHelper dbHelper = MainApp.getDbHelper();
|
||||||
// boluses
|
// boluses
|
||||||
|
for (Bolus pumpBolus : result.history.bolusHistory) {
|
||||||
|
Treatment aapsBolus = dbHelper.getTreatmentByDate(pumpBolus.timestamp);
|
||||||
|
if (aapsBolus == null) {
|
||||||
|
log.debug("Creating record from pump bolus: " + pumpBolus);
|
||||||
|
// info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage.findDetailedBolusInfo( ??)
|
||||||
|
DetailedBolusInfo dbi = new DetailedBolusInfo();
|
||||||
|
dbi.date = pumpBolus.timestamp;
|
||||||
|
dbi.insulin = pumpBolus.amount;
|
||||||
|
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
|
||||||
|
dbi.source = Source.USER;
|
||||||
|
MainApp.getConfigBuilder().addToHistoryTreatment(dbi);
|
||||||
|
MainApp.bus().post(new EventTreatmentChange()); // <- updates treatment-bolus tab
|
||||||
|
// TODO another event to fforce iobcalc recalc since earliest change? hm, seems autodetected :-)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TBRs
|
// TBRs
|
||||||
|
// TODO tolerance for start/end deviations? temp start is based on pump time, but in ms; round to seconds, so we can find it here more easily?
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
// TODO
|
// TODO
|
||||||
|
CommandResult refreshResult = runCommand("Refreshing", 3, ruffyScripter::readReservoirLevelAndLastBolus);
|
||||||
|
updateLocalData(refreshResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -787,7 +787,7 @@
|
||||||
<string name="enable_pump_unreachable_alert">Alert if pump unreachable for 30 min</string>
|
<string name="enable_pump_unreachable_alert">Alert if pump unreachable for 30 min</string>
|
||||||
<string name="combo_pump_never_connected">Never</string>
|
<string name="combo_pump_never_connected">Never</string>
|
||||||
<string name="combo_reservoir_level_insufficant_for_bolus">Not enough insulin left in reservoir for bolus</string>
|
<string name="combo_reservoir_level_insufficant_for_bolus">Not enough insulin left in reservoir for bolus</string>
|
||||||
<string name="combo_pump_bolus_history_state_mismatch">A bolus has been given recently on the pump directly of which AndroidAPS has only just become aware of. The pump\'s history is currently being read. Please check che Combo page, verify last bolus and IOB and bolus again if needed. No bolus has been given.</string>
|
<string name="combo_pump_bolus_history_state_mismatch">A bolus has been given recently on the pump directly of which AndroidAPS has only just become aware of. The pump\'s history is currently being read. Please check the Combo page, verify the last bolus and IOB and bolus again if needed. No bolus has been given.</string>
|
||||||
<string name="combo_pump_bolus_verification_failed">Bolus delivery verification failed. The pump history will be read again on the next loop run or when refreshing from the Combo page. Please check and bolus again if needed.</string>
|
<string name="combo_pump_bolus_verification_failed">Bolus delivery verification failed. The pump history will be read again on the next loop run or when refreshing from the Combo page. Please check and bolus again if needed.</string>
|
||||||
<string name="combo_pump_unsupported_operation">Requested operation not supported by pump</string>
|
<string name="combo_pump_unsupported_operation">Requested operation not supported by pump</string>
|
||||||
<string name="combo_bolus_bolus_delivery_failed">Bolus delivery failed. A (partial) bolus might have been delivered. Attempting to update history from pump. Please check the Combo page and bolus again as needed.</string>
|
<string name="combo_bolus_bolus_delivery_failed">Bolus delivery failed. A (partial) bolus might have been delivered. Attempting to update history from pump. Please check the Combo page and bolus again as needed.</string>
|
||||||
|
|
|
@ -8,6 +8,27 @@ public class Bolus extends HistoryRecord {
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
Bolus bolus = (Bolus) o;
|
||||||
|
|
||||||
|
if (timestamp != bolus.timestamp) return false;
|
||||||
|
return Double.compare(bolus.amount, amount) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
long temp;
|
||||||
|
result = (int) (timestamp ^ (timestamp >>> 32));
|
||||||
|
temp = Double.doubleToLongBits(amount);
|
||||||
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Bolus{" +
|
return "Bolus{" +
|
||||||
|
|
Loading…
Reference in a new issue