commit
e3c4de8f7b
31 changed files with 224 additions and 102 deletions
|
@ -1,36 +1,39 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<!-- Create a file appender for a log in the application's data directory -->
|
<!-- Create a file appender for a log in the application's data directory -->
|
||||||
<property scope="context" name="EXT_FILES_DIR" value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files"/>
|
<property name="EXT_FILES_DIR" scope="context"
|
||||||
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files" />
|
||||||
<file>${EXT_FILES_DIR}/AndroidAPS.log</file>
|
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
<file>${EXT_FILES_DIR}/AndroidAPS.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
<!-- daily rollover. Make sure the path matches the one in the file element or else
|
<!-- daily rollover. Make sure the path matches the one in the file element or else
|
||||||
the rollover logs are placed in the working directory. -->
|
the rollover logs are placed in the working directory. -->
|
||||||
<fileNamePattern>${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip</fileNamePattern>
|
<fileNamePattern>${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip
|
||||||
|
</fileNamePattern>
|
||||||
|
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
<timeBasedFileNamingAndTriggeringPolicy
|
||||||
|
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
<maxFileSize>5MB</maxFileSize>
|
<maxFileSize>5MB</maxFileSize>
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
<!-- keep 30 days' worth of history -->
|
<!-- keep 30 days' worth of history -->
|
||||||
<maxHistory>120</maxHistory>
|
<maxHistory>120</maxHistory>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [%class:%line]: %msg%n</pattern>
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [%class{0}.%M\(\):%line]: %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
|
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
|
||||||
<tagEncoder>
|
<tagEncoder>
|
||||||
<pattern>%logger{0}</pattern>
|
<pattern>%logger{0}</pattern>
|
||||||
</tagEncoder>
|
</tagEncoder>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>[%thread] %-5level [%class:%line]: %msg%n</pattern>
|
<pattern>[%thread] [%class{0}.%M\(\):%line]: %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- Write INFO (and higher-level) messages to the log file -->
|
<!-- Write INFO (and higher-level) messages to the log file -->
|
||||||
<root level="DEBUG">
|
<root level="DEBUG">
|
||||||
<appender-ref ref="file" />
|
<appender-ref ref="file" />
|
||||||
<appender-ref ref="logcat" />
|
<appender-ref ref="logcat" />
|
||||||
</root>
|
</root>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -50,7 +50,7 @@ public interface TreatmentsInterface {
|
||||||
|
|
||||||
boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus);
|
boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus);
|
||||||
|
|
||||||
boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo);
|
boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate);
|
||||||
|
|
||||||
TempTarget getTempTargetFromHistory();
|
TempTarget getTempTargetFromHistory();
|
||||||
TempTarget getTempTargetFromHistory(long time);
|
TempTarget getTempTargetFromHistory(long time);
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class AutosensData implements DataPointWithLabelInterface {
|
||||||
public double avgDelta = 0d;
|
public double avgDelta = 0d;
|
||||||
public double avgDeviation = 0d;
|
public double avgDeviation = 0d;
|
||||||
|
|
||||||
public double autosensRatio = 1d;
|
public AutosensResult autosensResult = new AutosensResult();
|
||||||
public double slopeFromMaxDeviation = 0;
|
public double slopeFromMaxDeviation = 0;
|
||||||
public double slopeFromMinDeviation = 999;
|
public double slopeFromMinDeviation = 999;
|
||||||
public double usedMinCarbsImpact = 0d;
|
public double usedMinCarbsImpact = 0d;
|
||||||
|
@ -86,7 +86,7 @@ public class AutosensData implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;
|
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensResult.ratio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int minOld() {
|
public int minOld() {
|
||||||
|
|
|
@ -137,6 +137,10 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadBgData(long start) {
|
void loadBgData(long start) {
|
||||||
|
if (start < oldestDataAvailable()) {
|
||||||
|
start = oldestDataAvailable();
|
||||||
|
log.debug("Limiting BG data to oldest data available: " + DateUtil.dateAndTimeString(start));
|
||||||
|
}
|
||||||
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (start - 60 * 60 * 1000L * (24 + dia)), false);
|
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (start - 60 * 60 * 1000L * (24 + dia)), false);
|
||||||
log.debug("BG data loaded. Size: " + bgReadings.size() + " Start date: " + DateUtil.dateAndTimeString(start));
|
log.debug("BG data loaded. Size: " + bgReadings.size() + " Start date: " + DateUtil.dateAndTimeString(start));
|
||||||
}
|
}
|
||||||
|
@ -388,10 +392,10 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
||||||
time = roundUpTime(previous);
|
time = roundUpTime(previous);
|
||||||
AutosensData data = autosensDataTable.get(time);
|
AutosensData data = autosensDataTable.get(time);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
//log.debug(">>> getAutosensData Cache hit " + data.log(time));
|
//log.debug(">>> AUTOSENSDATA Cache hit " + data.toString());
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
// log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString());
|
//log.debug(">>> AUTOSENSDATA Cache miss " + new Date(time).toLocaleString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,6 +403,14 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public AutosensData getLastAutosensDataSynchronized(String reason) {
|
public AutosensData getLastAutosensDataSynchronized(String reason) {
|
||||||
|
if (thread != null && thread.isAlive()) {
|
||||||
|
log.debug("AUTOSENSDATA is waiting for calculation thread: " + reason);
|
||||||
|
try {
|
||||||
|
thread.join(5000);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
log.debug("AUTOSENSDATA finished waiting for calculation thread: " + reason);
|
||||||
|
}
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
return getLastAutosensData(reason);
|
return getLastAutosensData(reason);
|
||||||
}
|
}
|
||||||
|
@ -452,6 +464,7 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
||||||
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
log.debug("AUTOSENSDATA (" + reason + ") " + data.toString());
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,14 +510,10 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
||||||
|
|
||||||
public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
return detectSensitivity(fromTime, toTime);
|
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
|
||||||
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
|
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
|
||||||
JSONArray array = new JSONArray();
|
JSONArray array = new JSONArray();
|
||||||
for (int i = 0; i < iobArray.length; i++) {
|
for (int i = 0; i < iobArray.length; i++) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
||||||
import com.crashlytics.android.answers.CustomEvent;
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
@ -69,6 +70,7 @@ public class IobCobOref1Thread extends Thread {
|
||||||
public final void run() {
|
public final void run() {
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
try {
|
try {
|
||||||
|
log.debug("AUTOSENSDATA thread started: " + from);
|
||||||
if (MainApp.getConfigBuilder() == null) {
|
if (MainApp.getConfigBuilder() == null) {
|
||||||
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
||||||
return; // app still initializing
|
return; // app still initializing
|
||||||
|
@ -341,16 +343,19 @@ public class IobCobOref1Thread extends Thread {
|
||||||
AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivityWithLock(oldestTimeWithData, bgTime);
|
AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivityWithLock(oldestTimeWithData, bgTime);
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug("Sensitivity result: " + sensitivity.toString());
|
log.debug("Sensitivity result: " + sensitivity.toString());
|
||||||
autosensData.autosensRatio = sensitivity.ratio;
|
autosensData.autosensResult = sensitivity;
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug(autosensData.toString());
|
log.debug(autosensData.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
new Thread(() -> {
|
||||||
log.debug("Finishing calculation thread: " + from);
|
SystemClock.sleep(1000);
|
||||||
|
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
||||||
|
}).start();
|
||||||
} finally {
|
} finally {
|
||||||
mWakeLock.release();
|
mWakeLock.release();
|
||||||
MainApp.bus().post(new EventIobCalculationProgress(""));
|
MainApp.bus().post(new EventIobCalculationProgress(""));
|
||||||
|
log.debug("AUTOSENSDATA thread ended: " + from);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
||||||
import com.crashlytics.android.answers.CustomEvent;
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
@ -68,6 +69,7 @@ public class IobCobThread extends Thread {
|
||||||
public final void run() {
|
public final void run() {
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
try {
|
try {
|
||||||
|
log.debug("AUTOSENSDATA thread started: " + from);
|
||||||
if (MainApp.getConfigBuilder() == null) {
|
if (MainApp.getConfigBuilder() == null) {
|
||||||
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
||||||
return; // app still initializing
|
return; // app still initializing
|
||||||
|
@ -268,16 +270,19 @@ public class IobCobThread extends Thread {
|
||||||
AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivityWithLock(oldestTimeWithData, bgTime);
|
AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivityWithLock(oldestTimeWithData, bgTime);
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug("Sensitivity result: " + sensitivity.toString());
|
log.debug("Sensitivity result: " + sensitivity.toString());
|
||||||
autosensData.autosensRatio = sensitivity.ratio;
|
autosensData.autosensResult = sensitivity;
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug(autosensData.toString());
|
log.debug(autosensData.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
new Thread(() -> {
|
||||||
log.debug("Finishing calculation thread: " + from);
|
SystemClock.sleep(1000);
|
||||||
|
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
||||||
|
}).start();
|
||||||
} finally {
|
} finally {
|
||||||
mWakeLock.release();
|
mWakeLock.release();
|
||||||
MainApp.bus().post(new EventIobCalculationProgress(""));
|
MainApp.bus().post(new EventIobCalculationProgress(""));
|
||||||
|
log.debug("AUTOSENSDATA thread ended: " + from);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
|
||||||
|
|
||||||
startPart = new Date();
|
startPart = new Date();
|
||||||
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
|
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
|
||||||
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
|
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin").autosensResult;
|
||||||
} else {
|
} else {
|
||||||
lastAutosensResult = new AutosensResult();
|
lastAutosensResult = new AutosensResult();
|
||||||
lastAutosensResult.sensResult = "autosens disabled";
|
lastAutosensResult.sensResult = "autosens disabled";
|
||||||
|
|
|
@ -180,7 +180,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface {
|
||||||
|
|
||||||
startPart = new Date();
|
startPart = new Date();
|
||||||
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
|
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
|
||||||
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
|
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin").autosensResult;
|
||||||
} else {
|
} else {
|
||||||
lastAutosensResult = new AutosensResult();
|
lastAutosensResult = new AutosensResult();
|
||||||
lastAutosensResult.sensResult = "autosens disabled";
|
lastAutosensResult.sensResult = "autosens disabled";
|
||||||
|
|
|
@ -127,7 +127,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
|
||||||
startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt);
|
startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt);
|
||||||
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
|
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
|
||||||
startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt);
|
startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt);
|
||||||
startHypoTTCheckbox.setOnCheckedChangeListener(this);
|
|
||||||
|
|
||||||
editTime = view.findViewById(R.id.newcarbs_time);
|
editTime = view.findViewById(R.id.newcarbs_time);
|
||||||
editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
|
editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
|
||||||
|
@ -160,8 +159,8 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
|
||||||
if (bgReading != null && bgReading.value < 72) {
|
if (bgReading != null && bgReading.value < 72) {
|
||||||
startHypoTTCheckbox.setOnCheckedChangeListener(null);
|
startHypoTTCheckbox.setOnCheckedChangeListener(null);
|
||||||
startHypoTTCheckbox.setChecked(true);
|
startHypoTTCheckbox.setChecked(true);
|
||||||
startHypoTTCheckbox.setOnClickListener(this);
|
|
||||||
}
|
}
|
||||||
|
startHypoTTCheckbox.setOnClickListener(this);
|
||||||
|
|
||||||
setCancelable(true);
|
setCancelable(true);
|
||||||
getDialog().setCanceledOnTouchOutside(false);
|
getDialog().setCanceledOnTouchOutside(false);
|
||||||
|
@ -231,13 +230,13 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
// Logic to disable a selected radio when pressed. When a checked radio
|
// Logic to disable a selected radio when pressed: when a checked radio
|
||||||
// is pressed, no CheckChanged event is trigger, so register a Click event
|
// is pressed, no CheckChanged event is triggered, so register a Click event
|
||||||
// when checking a radio. Since Click events come after CheckChanged events,
|
// when checking a radio. Since Click events come after CheckChanged events,
|
||||||
// the Click event is triggered immediately after this. Thus, set toggingTT
|
// the Click event is triggered immediately after this. Thus, set togglingTT
|
||||||
// var to true, so that the first Click event fired after this is ignored.
|
// var to true, so that the first Click event fired after this is ignored.
|
||||||
// Radios remove themselves from Click events once unchecked.
|
// Radios remove themselves from Click events once unchecked.
|
||||||
// Since radios are not in a group, manually update their state.
|
// Since radios are not in a group, their state is manually updated here.
|
||||||
switch (buttonView.getId()) {
|
switch (buttonView.getId()) {
|
||||||
case R.id.newcarbs_activity_tt:
|
case R.id.newcarbs_activity_tt:
|
||||||
togglingTT = true;
|
togglingTT = true;
|
||||||
|
|
|
@ -286,7 +286,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
|
||||||
detailedBolusInfo.notes = notes;
|
detailedBolusInfo.notes = notes;
|
||||||
if (recordOnlyCheckbox.isChecked()) {
|
if (recordOnlyCheckbox.isChecked()) {
|
||||||
detailedBolusInfo.date = time;
|
detailedBolusInfo.date = time;
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
} else {
|
} else {
|
||||||
detailedBolusInfo.date = now();
|
detailedBolusInfo.date = now();
|
||||||
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
|
@ -187,7 +186,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
}
|
}
|
||||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("Bolus"));
|
FabricPrivacy.getInstance().logCustom(new CustomEvent("Bolus"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,7 +389,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
}
|
}
|
||||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("Wizard"));
|
FabricPrivacy.getInstance().logCustom(new CustomEvent("Wizard"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -879,7 +879,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
}
|
}
|
||||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard"));
|
FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,9 +490,9 @@ public class GraphData {
|
||||||
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
|
||||||
if (autosensData != null) {
|
if (autosensData != null) {
|
||||||
ratioArray.add(new ScaledDataPoint(time, autosensData.autosensRatio - 1, ratioScale));
|
ratioArray.add(new ScaledDataPoint(time, autosensData.autosensResult.ratio - 1, ratioScale));
|
||||||
maxRatioValueFound = Math.max(maxRatioValueFound, autosensData.autosensRatio - 1);
|
maxRatioValueFound = Math.max(maxRatioValueFound, autosensData.autosensResult.ratio - 1);
|
||||||
minRatioValueFound = Math.min(minRatioValueFound, autosensData.autosensRatio - 1);
|
minRatioValueFound = Math.min(minRatioValueFound, autosensData.autosensResult.ratio - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,10 +60,7 @@ import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
|
||||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
|
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
|
||||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
|
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
|
||||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd;
|
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd;
|
||||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
|
||||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
|
||||||
import info.nightscout.androidaps.queue.CommandQueue;
|
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
import info.nightscout.utils.FabricPrivacy;
|
import info.nightscout.utils.FabricPrivacy;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
@ -498,7 +495,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
|
||||||
return deliverBolus(detailedBolusInfo);
|
return deliverBolus(detailedBolusInfo);
|
||||||
} else {
|
} else {
|
||||||
// no bolus required, carb only treatment
|
// no bolus required, carb only treatment
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
|
|
||||||
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||||
bolusingEvent.t = new Treatment();
|
bolusingEvent.t = new Treatment();
|
||||||
|
@ -689,7 +686,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
|
||||||
dbi.source = Source.PUMP;
|
dbi.source = Source.PUMP;
|
||||||
dbi.insulin = lastPumpBolus.amount;
|
dbi.insulin = lastPumpBolus.amount;
|
||||||
try {
|
try {
|
||||||
boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi);
|
boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, false);
|
||||||
if (!treatmentCreated) {
|
if (!treatmentCreated) {
|
||||||
log.error("Adding treatment record overrode an existing record: " + dbi);
|
log.error("Adding treatment record overrode an existing record: " + dbi);
|
||||||
if (dbi.isSMB) {
|
if (dbi.isSMB) {
|
||||||
|
@ -1188,7 +1185,8 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
|
||||||
dbi.source = Source.PUMP;
|
dbi.source = Source.PUMP;
|
||||||
dbi.insulin = pumpBolus.amount;
|
dbi.insulin = pumpBolus.amount;
|
||||||
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
|
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
|
||||||
if (TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi)) {
|
if (TreatmentsPlugin.getPlugin().getService().getPumpRecordById(dbi.pumpId) == null) {
|
||||||
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, false);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
|
||||||
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
|
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
|
||||||
detailedBolusInfo.insulin = t.insulin;
|
detailedBolusInfo.insulin = t.insulin;
|
||||||
detailedBolusInfo.date = System.currentTimeMillis();
|
detailedBolusInfo.date = System.currentTimeMillis();
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
|
|
@ -202,7 +202,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
|
||||||
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
|
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
|
||||||
detailedBolusInfo.insulin = t.insulin;
|
detailedBolusInfo.insulin = t.insulin;
|
||||||
detailedBolusInfo.date = System.currentTimeMillis();
|
detailedBolusInfo.date = System.currentTimeMillis();
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
|
|
@ -133,14 +133,14 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet {
|
||||||
break;
|
break;
|
||||||
case DanaRPump.BOLUS:
|
case DanaRPump.BOLUS:
|
||||||
detailedBolusInfo.insulin = param1 / 100d;
|
detailedBolusInfo.insulin = param1 / 100d;
|
||||||
boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
||||||
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
||||||
status = "BOLUS " + DateUtil.timeString(datetime);
|
status = "BOLUS " + DateUtil.timeString(datetime);
|
||||||
break;
|
break;
|
||||||
case DanaRPump.DUALBOLUS:
|
case DanaRPump.DUALBOLUS:
|
||||||
detailedBolusInfo.insulin = param1 / 100d;
|
detailedBolusInfo.insulin = param1 / 100d;
|
||||||
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
||||||
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
||||||
status = "DUALBOLUS " + DateUtil.timeString(datetime);
|
status = "DUALBOLUS " + DateUtil.timeString(datetime);
|
||||||
|
@ -183,7 +183,7 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet {
|
||||||
emptyCarbsInfo.date = datetime.getTime();
|
emptyCarbsInfo.date = datetime.getTime();
|
||||||
emptyCarbsInfo.source = Source.PUMP;
|
emptyCarbsInfo.source = Source.PUMP;
|
||||||
emptyCarbsInfo.pumpId = datetime.getTime();
|
emptyCarbsInfo.pumpId = datetime.getTime();
|
||||||
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo);
|
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo, false);
|
||||||
log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g");
|
log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g");
|
||||||
status = "CARBS " + DateUtil.timeString(datetime);
|
status = "CARBS " + DateUtil.timeString(datetime);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -240,7 +240,7 @@ public class DanaRSService extends Service {
|
||||||
SystemClock.sleep(100);
|
SystemClock.sleep(100);
|
||||||
}
|
}
|
||||||
if (DanaRS_Packet_APS_History_Events.lastEventTimeLoaded != 0)
|
if (DanaRS_Packet_APS_History_Events.lastEventTimeLoaded != 0)
|
||||||
lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded - 45 * 60 * 1000L; // always load last 45 min
|
lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded - T.mins(1).msecs();
|
||||||
else
|
else
|
||||||
lastHistoryFetched = 0;
|
lastHistoryFetched = 0;
|
||||||
log.debug("Events loaded");
|
log.debug("Events loaded");
|
||||||
|
@ -272,7 +272,7 @@ public class DanaRSService extends Service {
|
||||||
// bleComm.sendMessage(msg);
|
// bleComm.sendMessage(msg);
|
||||||
DanaRS_Packet_APS_Set_Event_History msgSetHistoryEntry_v2 = new DanaRS_Packet_APS_Set_Event_History(DanaRPump.CARBS, carbtime, carbs, 0);
|
DanaRS_Packet_APS_Set_Event_History msgSetHistoryEntry_v2 = new DanaRS_Packet_APS_Set_Event_History(DanaRPump.CARBS, carbtime, carbs, 0);
|
||||||
bleComm.sendMessage(msgSetHistoryEntry_v2);
|
bleComm.sendMessage(msgSetHistoryEntry_v2);
|
||||||
lastHistoryFetched = carbtime - 60000;
|
lastHistoryFetched = Math.min(lastHistoryFetched, carbtime - T.mins(1).msecs());
|
||||||
}
|
}
|
||||||
|
|
||||||
final long bolusStart = System.currentTimeMillis();
|
final long bolusStart = System.currentTimeMillis();
|
||||||
|
|
|
@ -107,14 +107,14 @@ public class MsgHistoryEvents_v2 extends MessageBase {
|
||||||
break;
|
break;
|
||||||
case DanaRPump.BOLUS:
|
case DanaRPump.BOLUS:
|
||||||
detailedBolusInfo.insulin = param1 / 100d;
|
detailedBolusInfo.insulin = param1 / 100d;
|
||||||
boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
||||||
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
||||||
status = "BOLUS " + DateUtil.timeString(datetime);
|
status = "BOLUS " + DateUtil.timeString(datetime);
|
||||||
break;
|
break;
|
||||||
case DanaRPump.DUALBOLUS:
|
case DanaRPump.DUALBOLUS:
|
||||||
detailedBolusInfo.insulin = param1 / 100d;
|
detailedBolusInfo.insulin = param1 / 100d;
|
||||||
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
|
||||||
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
|
||||||
status = "DUALBOLUS " + DateUtil.timeString(datetime);
|
status = "DUALBOLUS " + DateUtil.timeString(datetime);
|
||||||
|
@ -157,7 +157,7 @@ public class MsgHistoryEvents_v2 extends MessageBase {
|
||||||
emptyCarbsInfo.date = datetime.getTime();
|
emptyCarbsInfo.date = datetime.getTime();
|
||||||
emptyCarbsInfo.source = Source.PUMP;
|
emptyCarbsInfo.source = Source.PUMP;
|
||||||
emptyCarbsInfo.pumpId = datetime.getTime();
|
emptyCarbsInfo.pumpId = datetime.getTime();
|
||||||
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo);
|
newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo, false);
|
||||||
log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g");
|
log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g");
|
||||||
status = "CARBS " + DateUtil.timeString(datetime);
|
status = "CARBS " + DateUtil.timeString(datetime);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -371,7 +371,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
|
||||||
mSerialIOThread.sendMessage(msg);
|
mSerialIOThread.sendMessage(msg);
|
||||||
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, carbtime, carbs, 0);
|
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, carbtime, carbs, 0);
|
||||||
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
|
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
|
||||||
lastHistoryFetched = carbtime - 60000;
|
lastHistoryFetched = Math.min(lastHistoryFetched, carbtime - T.mins(1).msecs());
|
||||||
}
|
}
|
||||||
|
|
||||||
final long bolusStart = System.currentTimeMillis();
|
final long bolusStart = System.currentTimeMillis();
|
||||||
|
@ -455,7 +455,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
|
||||||
mSerialIOThread.sendMessage(msg);
|
mSerialIOThread.sendMessage(msg);
|
||||||
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, time, amount, 0);
|
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, time, amount, 0);
|
||||||
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
|
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
|
||||||
lastHistoryFetched = time - 1;
|
lastHistoryFetched = Math.min(lastHistoryFetched, time - T.mins(1).msecs());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
|
||||||
}
|
}
|
||||||
SystemClock.sleep(200);
|
SystemClock.sleep(200);
|
||||||
if (MsgHistoryEvents_v2.lastEventTimeLoaded != 0)
|
if (MsgHistoryEvents_v2.lastEventTimeLoaded != 0)
|
||||||
lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - 45 * 60 * 1000L; //always load last 45 min;
|
lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - T.mins(1).msecs();
|
||||||
else
|
else
|
||||||
lastHistoryFetched = 0;
|
lastHistoryFetched = 0;
|
||||||
mDanaRPump.lastConnection = System.currentTimeMillis();
|
mDanaRPump.lastConnection = System.currentTimeMillis();
|
||||||
|
|
|
@ -61,7 +61,6 @@ import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfil
|
||||||
import sugar.free.sightparser.applayer.messages.AppLayerMessage;
|
import sugar.free.sightparser.applayer.messages.AppLayerMessage;
|
||||||
import sugar.free.sightparser.applayer.messages.remote_control.BolusMessage;
|
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.CancelBolusMessage;
|
||||||
import sugar.free.sightparser.applayer.messages.remote_control.CancelTBRMessage;
|
|
||||||
import sugar.free.sightparser.applayer.messages.remote_control.ExtendedBolusMessage;
|
import sugar.free.sightparser.applayer.messages.remote_control.ExtendedBolusMessage;
|
||||||
import sugar.free.sightparser.applayer.messages.remote_control.StandardBolusMessage;
|
import sugar.free.sightparser.applayer.messages.remote_control.StandardBolusMessage;
|
||||||
import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
|
import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
|
||||||
|
@ -456,7 +455,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
|
||||||
bolusingEvent.bolusId = bolusId;
|
bolusingEvent.bolusId = bolusId;
|
||||||
bolusingEvent.percent = 0;
|
bolusingEvent.percent = 0;
|
||||||
MainApp.bus().post(bolusingEvent);
|
MainApp.bus().post(bolusingEvent);
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
|
||||||
} else {
|
} else {
|
||||||
log.debug("Failure to deliver treatment");
|
log.debug("Failure to deliver treatment");
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,6 @@ class HistoryLogAdapter {
|
||||||
detailedBolusInfo.source = Source.PUMP;
|
detailedBolusInfo.source = Source.PUMP;
|
||||||
detailedBolusInfo.pumpId = record_id;
|
detailedBolusInfo.pumpId = record_id;
|
||||||
detailedBolusInfo.insulin = insulin;
|
detailedBolusInfo.insulin = insulin;
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
|
||||||
result.bolusDelivered = detailedBolusInfo.insulin;
|
result.bolusDelivered = detailedBolusInfo.insulin;
|
||||||
result.carbsDelivered = detailedBolusInfo.carbs;
|
result.carbsDelivered = detailedBolusInfo.carbs;
|
||||||
result.comment = MainApp.gs(R.string.virtualpump_resultok);
|
result.comment = MainApp.gs(R.string.virtualpump_resultok);
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
|
||||||
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 = new Date();
|
lastDataTime = new Date();
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class CarbsGenerator {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(carbInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(carbInfo, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,6 +132,24 @@ public class Treatment implements DataPointWithLabelInterface {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mealBolus, _id and isSMB cannot be known coming from pump. Only compare rest
|
||||||
|
* TODO: remove debug toasts
|
||||||
|
*/
|
||||||
|
public boolean equalsRePumpHistory(Treatment other) {
|
||||||
|
if (date != other.date) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (insulin != other.insulin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (carbs != other.carbs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void copyFrom(Treatment t) {
|
public void copyFrom(Treatment t) {
|
||||||
date = t.date;
|
date = t.date;
|
||||||
_id = t._id;
|
_id = t._id;
|
||||||
|
@ -142,6 +160,14 @@ public class Treatment implements DataPointWithLabelInterface {
|
||||||
isSMB = t.isSMB;
|
isSMB = t.isSMB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyBasics(Treatment t) {
|
||||||
|
date = t.date;
|
||||||
|
insulin = t.insulin;
|
||||||
|
carbs = t.carbs;
|
||||||
|
pumpId = t.pumpId;
|
||||||
|
source = t.source;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------- DataPointInterface --------------------
|
// ----------------- DataPointInterface --------------------
|
||||||
@Override
|
@Override
|
||||||
public double getX() {
|
public double getX() {
|
||||||
|
|
|
@ -241,28 +241,51 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if new record is created
|
// return true if new record is created
|
||||||
public boolean createOrUpdate(Treatment treatment) {
|
public UpdateReturn createOrUpdate(Treatment treatment) {
|
||||||
try {
|
try {
|
||||||
Treatment old;
|
Treatment old;
|
||||||
treatment.date = DatabaseHelper.roundDateToSec(treatment.date);
|
treatment.date = DatabaseHelper.roundDateToSec(treatment.date);
|
||||||
|
|
||||||
if (treatment.source == Source.PUMP) {
|
if (treatment.source == Source.PUMP) {
|
||||||
// check for changed from pump change in NS
|
// check for changed from pump change in NS
|
||||||
QueryBuilder<Treatment, Long> queryBuilder = getDao().queryBuilder();
|
Treatment existingTreatment = getPumpRecordById(treatment.pumpId);
|
||||||
Where where = queryBuilder.where();
|
if (existingTreatment != null) {
|
||||||
where.eq("pumpId", treatment.pumpId);
|
boolean equalRePumpHistory = existingTreatment.equalsRePumpHistory(treatment);
|
||||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
boolean sameSource = existingTreatment.source == treatment.source;
|
||||||
List<Treatment> trList = getDao().query(preparedQuery);
|
if(!equalRePumpHistory) {
|
||||||
if (trList.size() > 0) {
|
// another treatment exists. Update it with the treatment coming from the pump
|
||||||
// do nothing, pump history record cannot be changed
|
log.debug("TREATMENT: Pump record already found in database: " + existingTreatment.toString() + " wanting to add " + treatment.toString());
|
||||||
log.debug("TREATMENT: Pump record already found in database: " + treatment.toString());
|
long oldDate = existingTreatment.date;
|
||||||
return false;
|
getDao().delete(existingTreatment); // need to delete/create because date may change too
|
||||||
|
existingTreatment.copyBasics(treatment);
|
||||||
|
getDao().create(existingTreatment);
|
||||||
|
DatabaseHelper.updateEarliestDataChange(oldDate);
|
||||||
|
DatabaseHelper.updateEarliestDataChange(existingTreatment.date);
|
||||||
|
scheduleTreatmentChange(treatment);
|
||||||
|
return new UpdateReturn(sameSource, false); //updating a pump treatment with another one from the pump is not counted as clash
|
||||||
|
}
|
||||||
|
return new UpdateReturn(equalRePumpHistory, false);
|
||||||
|
}
|
||||||
|
existingTreatment = getDao().queryForId(treatment.date);
|
||||||
|
if (existingTreatment != null) {
|
||||||
|
// another treatment exists with different pumpID. Update it with the treatment coming from the pump
|
||||||
|
boolean equalRePumpHistory = existingTreatment.equalsRePumpHistory(treatment);
|
||||||
|
boolean sameSource = existingTreatment.source == treatment.source;
|
||||||
|
long oldDate = existingTreatment.date;
|
||||||
|
log.debug("TREATMENT: Pump record already found in database: " + existingTreatment.toString() + " wanting to add " + treatment.toString());
|
||||||
|
getDao().delete(existingTreatment); // need to delete/create because date may change too
|
||||||
|
existingTreatment.copyFrom(treatment);
|
||||||
|
getDao().create(existingTreatment);
|
||||||
|
DatabaseHelper.updateEarliestDataChange(oldDate);
|
||||||
|
DatabaseHelper.updateEarliestDataChange(existingTreatment.date);
|
||||||
|
scheduleTreatmentChange(treatment);
|
||||||
|
return new UpdateReturn(equalRePumpHistory || sameSource, false);
|
||||||
}
|
}
|
||||||
getDao().create(treatment);
|
getDao().create(treatment);
|
||||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||||
DatabaseHelper.updateEarliestDataChange(treatment.date);
|
DatabaseHelper.updateEarliestDataChange(treatment.date);
|
||||||
scheduleTreatmentChange(treatment);
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return new UpdateReturn(true, true);
|
||||||
}
|
}
|
||||||
if (treatment.source == Source.NIGHTSCOUT) {
|
if (treatment.source == Source.NIGHTSCOUT) {
|
||||||
old = getDao().queryForId(treatment.date);
|
old = getDao().queryForId(treatment.date);
|
||||||
|
@ -279,9 +302,9 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
DatabaseHelper.updateEarliestDataChange(old.date);
|
DatabaseHelper.updateEarliestDataChange(old.date);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange(treatment);
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return new UpdateReturn(true, true);
|
||||||
}
|
}
|
||||||
return false;
|
return new UpdateReturn(true, false);
|
||||||
}
|
}
|
||||||
// find by NS _id
|
// find by NS _id
|
||||||
if (treatment._id != null) {
|
if (treatment._id != null) {
|
||||||
|
@ -299,7 +322,7 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
DatabaseHelper.updateEarliestDataChange(old.date);
|
DatabaseHelper.updateEarliestDataChange(old.date);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange(treatment);
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return new UpdateReturn(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,19 +330,39 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||||
DatabaseHelper.updateEarliestDataChange(treatment.date);
|
DatabaseHelper.updateEarliestDataChange(treatment.date);
|
||||||
scheduleTreatmentChange(treatment);
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return new UpdateReturn(true, true);
|
||||||
}
|
}
|
||||||
if (treatment.source == Source.USER) {
|
if (treatment.source == Source.USER) {
|
||||||
getDao().create(treatment);
|
getDao().create(treatment);
|
||||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||||
DatabaseHelper.updateEarliestDataChange(treatment.date);
|
DatabaseHelper.updateEarliestDataChange(treatment.date);
|
||||||
scheduleTreatmentChange(treatment);
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return new UpdateReturn(true, true);
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
return false;
|
return new UpdateReturn(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the record for the given id, null if none, throws RuntimeException
|
||||||
|
* if multiple records with the same pump id exist. */
|
||||||
|
@Nullable
|
||||||
|
public Treatment getPumpRecordById(long pumpId) {
|
||||||
|
try {
|
||||||
|
QueryBuilder<Treatment, Long> queryBuilder = getDao().queryBuilder();
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.eq("pumpId", pumpId);
|
||||||
|
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||||
|
List<Treatment> result = getDao().query(preparedQuery);
|
||||||
|
switch (result.size()) {
|
||||||
|
case 0: return null;
|
||||||
|
case 1: return result.get(0);
|
||||||
|
default: throw new RuntimeException("Multiple records with the same pump id found: " + result.toString());
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteNS(JSONObject json) {
|
public void deleteNS(JSONObject json) {
|
||||||
|
@ -423,4 +466,14 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class UpdateReturn {
|
||||||
|
public UpdateReturn(boolean success, boolean newRecord){
|
||||||
|
this.success = success;
|
||||||
|
this.newRecord = newRecord;
|
||||||
|
}
|
||||||
|
boolean newRecord;
|
||||||
|
boolean success;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package info.nightscout.androidaps.plugins.Treatments;
|
package info.nightscout.androidaps.plugins.Treatments;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -38,11 +40,13 @@ import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
|
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
|
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.FabricPrivacy;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
import info.nightscout.utils.T;
|
import info.nightscout.utils.T;
|
||||||
|
@ -465,7 +469,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
|
||||||
|
|
||||||
// return true if new record is created
|
// return true if new record is created
|
||||||
@Override
|
@Override
|
||||||
public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo) {
|
public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) {
|
||||||
Treatment treatment = new Treatment();
|
Treatment treatment = new Treatment();
|
||||||
treatment.date = detailedBolusInfo.date;
|
treatment.date = detailedBolusInfo.date;
|
||||||
treatment.source = detailedBolusInfo.source;
|
treatment.source = detailedBolusInfo.source;
|
||||||
|
@ -477,7 +481,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
|
||||||
treatment.carbs = detailedBolusInfo.carbs;
|
treatment.carbs = detailedBolusInfo.carbs;
|
||||||
treatment.source = detailedBolusInfo.source;
|
treatment.source = detailedBolusInfo.source;
|
||||||
treatment.mealBolus = treatment.carbs > 0;
|
treatment.mealBolus = treatment.carbs > 0;
|
||||||
boolean newRecordCreated = getService().createOrUpdate(treatment);
|
TreatmentService.UpdateReturn creatOrUpdateResult = getService().createOrUpdate(treatment);
|
||||||
|
boolean newRecordCreated = creatOrUpdateResult.newRecord;
|
||||||
//log.debug("Adding new Treatment record" + treatment.toString());
|
//log.debug("Adding new Treatment record" + treatment.toString());
|
||||||
if (detailedBolusInfo.carbTime != 0) {
|
if (detailedBolusInfo.carbTime != 0) {
|
||||||
Treatment carbsTreatment = new Treatment();
|
Treatment carbsTreatment = new Treatment();
|
||||||
|
@ -491,6 +496,24 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
|
||||||
}
|
}
|
||||||
if (newRecordCreated && detailedBolusInfo.isValid)
|
if (newRecordCreated && detailedBolusInfo.isValid)
|
||||||
NSUpload.uploadTreatmentRecord(detailedBolusInfo);
|
NSUpload.uploadTreatmentRecord(detailedBolusInfo);
|
||||||
|
|
||||||
|
if (!allowUpdate && !creatOrUpdateResult.success) {
|
||||||
|
log.error("Treatment could not be added to DB", new Exception());
|
||||||
|
|
||||||
|
String status = String.format(MainApp.gs(R.string.error_adding_treatment_message), treatment.insulin, (int) treatment.carbs, DateUtil.dateAndTimeString(treatment.date));
|
||||||
|
|
||||||
|
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||||
|
i.putExtra("soundid", R.raw.error);
|
||||||
|
i.putExtra("title", MainApp.gs(R.string.error_adding_treatment_title));
|
||||||
|
i.putExtra("status", status);
|
||||||
|
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
MainApp.instance().startActivity(i);
|
||||||
|
|
||||||
|
CustomEvent customEvent = new CustomEvent("TreatmentClash");
|
||||||
|
customEvent.putCustomAttribute("status", status);
|
||||||
|
FabricPrivacy.getInstance().logCustom(customEvent);
|
||||||
|
}
|
||||||
|
|
||||||
return newRecordCreated;
|
return newRecordCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -719,7 +719,7 @@ public class ActionStringHandler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
|
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1163,6 +1163,9 @@
|
||||||
<string name="careportal_removestartedevents">Clean AndroidAPS started</string>
|
<string name="careportal_removestartedevents">Clean AndroidAPS started</string>
|
||||||
<string name="storedsettingsfound">Stored settings found</string>
|
<string name="storedsettingsfound">Stored settings found</string>
|
||||||
<string name="allow_hardware_pump_text">Attention: If you activate and connect to a hardware pump, AndroidAPS will copy the basal settings from the profile to the pump, overwriting the existing basal rate stored on the pump. Make sure you have the correct basal setting in AndroidAPS. If you are not sure or don\'t want to overwrite the basal settings on your pump, press cancel and repeat switching to the pump at a later time.</string>
|
<string name="allow_hardware_pump_text">Attention: If you activate and connect to a hardware pump, AndroidAPS will copy the basal settings from the profile to the pump, overwriting the existing basal rate stored on the pump. Make sure you have the correct basal setting in AndroidAPS. If you are not sure or don\'t want to overwrite the basal settings on your pump, press cancel and repeat switching to the pump at a later time.</string>
|
||||||
|
<string name="error_adding_treatment_title">Treatment data incomplete</string>
|
||||||
|
<!-- TODO convert to proper style -->
|
||||||
|
<string name="error_adding_treatment_message" formatted="false">A treatment (insulin: %.2f, carbs: %d, at: %s) could not be added to treatments. Please check and manually add a record as appropriate.</string>
|
||||||
<string name="generated_ecarbs_note">Generated eCarbs with amount: %1$dg, duration: %2$dh, delay: %3$dm</string>
|
<string name="generated_ecarbs_note">Generated eCarbs with amount: %1$dg, duration: %2$dh, delay: %3$dm</string>
|
||||||
<string name="key_plugin_stats_report_timestamp" translatable="false">key_plugin_stats_report_timestamp</string>
|
<string name="key_plugin_stats_report_timestamp" translatable="false">key_plugin_stats_report_timestamp</string>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue