Merge remote-tracking branch 'origin/dev' into combo-scripter-v2
This commit is contained in:
commit
c469edb5a3
|
@ -15,20 +15,22 @@ import org.slf4j.LoggerFactory;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
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.ProfileStore;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.CareportalEvent;
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
|
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
|
||||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||||
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||||
|
@ -37,7 +39,6 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
|
||||||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
|
||||||
import info.nightscout.utils.BundleLogger;
|
import info.nightscout.utils.BundleLogger;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
@ -365,8 +366,10 @@ public class DataService extends IntentService {
|
||||||
String profile = bundles.getString("profile");
|
String profile = bundles.getString("profile");
|
||||||
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
|
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
|
||||||
NSProfilePlugin.storeNewProfile(profileStore);
|
NSProfilePlugin.storeNewProfile(profileStore);
|
||||||
|
MainApp.bus().post(new EventNSProfileUpdateGUI());
|
||||||
|
// if there are no profile switches this should lead to profile update
|
||||||
|
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
|
||||||
MainApp.bus().post(new EventNewBasalProfile());
|
MainApp.bus().post(new EventNewBasalProfile());
|
||||||
|
|
||||||
if (Config.logIncommingData)
|
if (Config.logIncommingData)
|
||||||
log.debug("Received profileStore: " + activeProfile + " " + profile);
|
log.debug("Received profileStore: " + activeProfile + " " + profile);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 23.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EventAppInitialized extends Event {
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
import info.nightscout.androidaps.db.TempTarget;
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
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.EventAppInitialized;
|
||||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||||
|
@ -144,6 +145,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
pluginList = MainApp.getPluginsList();
|
pluginList = MainApp.getPluginsList();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
MainApp.bus().post(new EventAppInitialized());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeSettings() {
|
public void storeSettings() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.SystemClock;
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
||||||
|
@ -24,14 +22,13 @@ import info.nightscout.androidaps.data.IobTotal;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||||
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
||||||
import info.nightscout.androidaps.events.EventNewBG;
|
import info.nightscout.androidaps.events.EventNewBG;
|
||||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
|
@ -51,10 +48,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
private static double dia = Constants.defaultDIA;
|
private static double dia = Constants.defaultDIA;
|
||||||
|
|
||||||
private static Handler sHandler = null;
|
static final Object dataLock = new Object();
|
||||||
private static HandlerThread sHandlerThread = null;
|
|
||||||
|
|
||||||
private static final Object dataLock = new Object();
|
boolean stopCalculationTrigger = false;
|
||||||
|
IobCobThread thread = null;
|
||||||
|
|
||||||
private static IobCobCalculatorPlugin plugin = null;
|
private static IobCobCalculatorPlugin plugin = null;
|
||||||
|
|
||||||
|
@ -134,12 +131,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
IobCobCalculatorPlugin() {
|
IobCobCalculatorPlugin() {
|
||||||
MainApp.bus().register(this);
|
MainApp.bus().register(this);
|
||||||
if (sHandlerThread == null) {
|
|
||||||
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName(), Process.THREAD_PRIORITY_LOWEST);
|
|
||||||
sHandlerThread.start();
|
|
||||||
sHandler = new Handler(sHandlerThread.getLooper());
|
|
||||||
}
|
|
||||||
onNewBg(new EventNewBG());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -176,15 +167,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return rouded;
|
return rouded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadBgData() {
|
void loadBgData() {
|
||||||
//log.debug("Locking loadBgData");
|
|
||||||
synchronized (dataLock) {
|
|
||||||
onNewProfile(null);
|
|
||||||
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
|
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
|
||||||
log.debug("BG data loaded. Size: " + bgReadings.size());
|
log.debug("BG data loaded. Size: " + bgReadings.size());
|
||||||
}
|
}
|
||||||
//log.debug("Releasing loadBgData");
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAbout5minData() {
|
private boolean isAbout5minData() {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
|
@ -210,7 +196,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBucketedData() {
|
void createBucketedData() {
|
||||||
if (isAbout5minData())
|
if (isAbout5minData())
|
||||||
createBucketedData5min();
|
createBucketedData5min();
|
||||||
else
|
else
|
||||||
|
@ -242,7 +228,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBucketedDataRecalculated() {
|
private void createBucketedDataRecalculated() {
|
||||||
synchronized (dataLock) {
|
|
||||||
if (bgReadings == null || bgReadings.size() < 3) {
|
if (bgReadings == null || bgReadings.size() < 3) {
|
||||||
bucketed_data = null;
|
bucketed_data = null;
|
||||||
return;
|
return;
|
||||||
|
@ -272,12 +257,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void createBucketedData5min() {
|
public void createBucketedData5min() {
|
||||||
//log.debug("Locking createBucketedData");
|
|
||||||
synchronized (dataLock) {
|
|
||||||
if (bgReadings == null || bgReadings.size() < 3) {
|
if (bgReadings == null || bgReadings.size() < 3) {
|
||||||
bucketed_data = null;
|
bucketed_data = null;
|
||||||
return;
|
return;
|
||||||
|
@ -338,128 +320,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
log.debug("Bucketed data created. Size: " + bucketed_data.size());
|
log.debug("Bucketed data created. Size: " + bucketed_data.size());
|
||||||
}
|
}
|
||||||
//log.debug("Releasing createBucketedData");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateSensitivityData() {
|
|
||||||
if (MainApp.getConfigBuilder() == null)
|
|
||||||
return; // app still initializing
|
|
||||||
if (MainApp.getConfigBuilder().getProfile() == null)
|
|
||||||
return; // app still initializing
|
|
||||||
//log.debug("Locking calculateSensitivityData");
|
|
||||||
long oldestTimeWithData = oldestDataAvailable();
|
|
||||||
|
|
||||||
synchronized (dataLock) {
|
|
||||||
|
|
||||||
if (bucketed_data == null || bucketed_data.size() < 3) {
|
|
||||||
log.debug("calculateSensitivityData: No bucketed data available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
|
|
||||||
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
|
|
||||||
AutosensData previous = autosensDataTable.get(prevDataTime);
|
|
||||||
// start from oldest to be able sub cob
|
|
||||||
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
|
|
||||||
// check if data already exists
|
|
||||||
long bgTime = bucketed_data.get(i).date;
|
|
||||||
bgTime = roundUpTime(bgTime);
|
|
||||||
if (bgTime > System.currentTimeMillis())
|
|
||||||
continue;
|
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
|
||||||
|
|
||||||
AutosensData existing;
|
|
||||||
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
|
||||||
previous = existing;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profile.getIsf(bgTime) == null)
|
|
||||||
return; // profile not set yet
|
|
||||||
|
|
||||||
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
|
|
||||||
|
|
||||||
AutosensData autosensData = new AutosensData();
|
|
||||||
autosensData.time = bgTime;
|
|
||||||
if (previous != null)
|
|
||||||
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
|
|
||||||
else
|
|
||||||
autosensData.activeCarbsList = new ArrayList<>();
|
|
||||||
|
|
||||||
//console.error(bgTime , bucketed_data[i].glucose);
|
|
||||||
double bg;
|
|
||||||
double avgDelta;
|
|
||||||
double delta;
|
|
||||||
bg = bucketed_data.get(i).value;
|
|
||||||
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
|
|
||||||
log.error("! value < 39");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
delta = (bg - bucketed_data.get(i + 1).value);
|
|
||||||
|
|
||||||
IobTotal iob = calculateFromTreatmentsAndTemps(bgTime);
|
|
||||||
|
|
||||||
double bgi = -iob.activity * sens * 5;
|
|
||||||
double deviation = delta - bgi;
|
|
||||||
|
|
||||||
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
|
||||||
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
|
||||||
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
|
|
||||||
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// if we are absorbing carbs
|
|
||||||
if (previous != null && previous.cob > 0) {
|
|
||||||
// calculate sum of min carb impact from all active treatments
|
|
||||||
double totalMinCarbsImpact = 0d;
|
|
||||||
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
|
||||||
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
|
||||||
totalMinCarbsImpact += c.min5minCarbImpact;
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out how many carbs that represents
|
|
||||||
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
|
|
||||||
double ci = Math.max(deviation, totalMinCarbsImpact);
|
|
||||||
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
|
|
||||||
// and add that to the running total carbsAbsorbed
|
|
||||||
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
|
|
||||||
autosensData.substractAbosorbedCarbs();
|
|
||||||
}
|
|
||||||
autosensData.removeOldCarbs(bgTime);
|
|
||||||
autosensData.cob += autosensData.carbsFromBolus;
|
|
||||||
autosensData.deviation = deviation;
|
|
||||||
autosensData.bgi = bgi;
|
|
||||||
autosensData.delta = delta;
|
|
||||||
|
|
||||||
// calculate autosens only without COB
|
|
||||||
if (autosensData.cob <= 0) {
|
|
||||||
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
|
|
||||||
autosensData.pastSensitivity += "=";
|
|
||||||
autosensData.nonEqualDeviation = true;
|
|
||||||
} else if (deviation > 0) {
|
|
||||||
autosensData.pastSensitivity += "+";
|
|
||||||
autosensData.nonEqualDeviation = true;
|
|
||||||
} else {
|
|
||||||
autosensData.pastSensitivity += "-";
|
|
||||||
autosensData.nonEqualDeviation = true;
|
|
||||||
}
|
|
||||||
autosensData.nonCarbsDeviation = true;
|
|
||||||
} else {
|
|
||||||
autosensData.pastSensitivity += "C";
|
|
||||||
}
|
|
||||||
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
|
||||||
|
|
||||||
previous = autosensData;
|
|
||||||
autosensDataTable.put(bgTime, autosensData);
|
|
||||||
autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio;
|
|
||||||
if (Config.logAutosensData)
|
|
||||||
log.debug(autosensData.log(bgTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MainApp.bus().post(new EventAutosensCalculationFinished());
|
|
||||||
//log.debug("Releasing calculateSensitivityData");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long oldestDataAvailable() {
|
public static long oldestDataAvailable() {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
@ -613,7 +473,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
||||||
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,15 +486,33 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNewBg(EventNewBG ev) {
|
public void onEventAppInitialized(EventAppInitialized ev) {
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventAppInitialized", true);
|
||||||
@Override
|
}
|
||||||
public void run() {
|
|
||||||
loadBgData();
|
@Subscribe
|
||||||
createBucketedData();
|
public void onEventNewBG(EventNewBG ev) {
|
||||||
calculateSensitivityData();
|
stopCalculation("onEventNewBG");
|
||||||
|
runCalculation("onEventNewBG", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopCalculation(String from) {
|
||||||
|
if (thread != null && thread.getState() != Thread.State.TERMINATED) {
|
||||||
|
stopCalculationTrigger = true;
|
||||||
|
log.debug("Stopping calculation thread: " + from);
|
||||||
|
while (thread.getState() != Thread.State.TERMINATED) {
|
||||||
|
SystemClock.sleep(100);
|
||||||
|
}
|
||||||
|
log.debug("Calculation thread stopped: " + from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runCalculation(String from, boolean bgDataReload) {
|
||||||
|
log.debug("Starting calculation thread: " + from);
|
||||||
|
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
||||||
|
thread = new IobCobThread(this, from, bgDataReload);
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
@ -648,64 +526,53 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
if (ev == null) { // on init no need of reset
|
if (ev == null) { // on init no need of reset
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
stopCalculation("onNewProfile");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onNewProfile", false);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(EventPreferenceChange ev) {
|
public void onEventPreferenceChange(EventPreferenceChange ev) {
|
||||||
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
|
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
|
||||||
ev.isChanged(R.string.key_age) ||
|
ev.isChanged(R.string.key_age) ||
|
||||||
ev.isChanged(R.string.key_absorption_maxtime)
|
ev.isChanged(R.string.key_absorption_maxtime)
|
||||||
) {
|
) {
|
||||||
|
stopCalculation("onEventPreferenceChange");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventPreferenceChange", false);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(EventConfigBuilderChange ev) {
|
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
|
||||||
|
stopCalculation("onEventConfigBuilderChange");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventConfigBuilderChange", false);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNewHistoryData(EventNewHistoryData ev) {
|
public void onEventNewHistoryData(EventNewHistoryData ev) {
|
||||||
//log.debug("Locking onNewHistoryData");
|
//log.debug("Locking onNewHistoryData");
|
||||||
|
stopCalculation("onEventNewHistoryData");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
long time = ev.time;
|
// clear up 5 min back for proper COB calculation
|
||||||
|
long time = ev.time - 5 * 60 * 1000L;
|
||||||
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
|
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
|
||||||
for (int index = iobTable.size() - 1; index >= 0; index--) {
|
for (int index = iobTable.size() - 1; index >= 0; index--) {
|
||||||
if (iobTable.keyAt(index) > time) {
|
if (iobTable.keyAt(index) > time) {
|
||||||
if (Config.logAutosensData)
|
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
|
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
|
||||||
iobTable.removeAt(index);
|
iobTable.removeAt(index);
|
||||||
|
@ -732,12 +599,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventNewHistoryData", false);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//log.debug("Releasing onNewHistoryData");
|
//log.debug("Releasing onNewHistoryData");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||||
|
import info.nightscout.androidaps.queue.QueueThread;
|
||||||
|
|
||||||
|
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.getBucketedData;
|
||||||
|
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.oldestDataAvailable;
|
||||||
|
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.roundUpTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 23.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class IobCobThread extends Thread {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
|
||||||
|
|
||||||
|
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||||
|
private boolean bgDataReload;
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
|
||||||
|
public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.iobCobCalculatorPlugin = plugin;
|
||||||
|
this.bgDataReload = bgDataReload;
|
||||||
|
this.from = from;
|
||||||
|
|
||||||
|
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||||
|
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void run() {
|
||||||
|
mWakeLock.acquire();
|
||||||
|
try {
|
||||||
|
if (MainApp.getConfigBuilder() == null) {
|
||||||
|
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
||||||
|
return; // app still initializing
|
||||||
|
}
|
||||||
|
if (MainApp.getConfigBuilder().getProfile() == null) {
|
||||||
|
log.debug("Aborting calculation thread (No profile): " + from);
|
||||||
|
return; // app still initializing
|
||||||
|
}
|
||||||
|
//log.debug("Locking calculateSensitivityData");
|
||||||
|
|
||||||
|
Object dataLock = iobCobCalculatorPlugin.dataLock;
|
||||||
|
|
||||||
|
long oldestTimeWithData = oldestDataAvailable();
|
||||||
|
|
||||||
|
synchronized (dataLock) {
|
||||||
|
if (bgDataReload) {
|
||||||
|
iobCobCalculatorPlugin.loadBgData();
|
||||||
|
iobCobCalculatorPlugin.createBucketedData();
|
||||||
|
}
|
||||||
|
List<BgReading> bucketed_data = getBucketedData();
|
||||||
|
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
|
||||||
|
|
||||||
|
if (bucketed_data == null || bucketed_data.size() < 3) {
|
||||||
|
log.debug("Aborting calculation thread (No bucketed data available): " + from);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
|
||||||
|
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
|
||||||
|
AutosensData previous = autosensDataTable.get(prevDataTime);
|
||||||
|
// start from oldest to be able sub cob
|
||||||
|
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
|
||||||
|
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
|
||||||
|
iobCobCalculatorPlugin.stopCalculationTrigger = false;
|
||||||
|
log.debug("Aborting calculation thread (trigger): " + from);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check if data already exists
|
||||||
|
long bgTime = bucketed_data.get(i).date;
|
||||||
|
bgTime = roundUpTime(bgTime);
|
||||||
|
if (bgTime > System.currentTimeMillis())
|
||||||
|
continue;
|
||||||
|
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
||||||
|
|
||||||
|
AutosensData existing;
|
||||||
|
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
||||||
|
previous = existing;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile.getIsf(bgTime) == null) {
|
||||||
|
log.debug("Aborting calculation thread (no ISF): " + from);
|
||||||
|
return; // profile not set yet
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.logAutosensData)
|
||||||
|
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
|
||||||
|
|
||||||
|
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
|
||||||
|
|
||||||
|
AutosensData autosensData = new AutosensData();
|
||||||
|
autosensData.time = bgTime;
|
||||||
|
if (previous != null)
|
||||||
|
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
|
||||||
|
else
|
||||||
|
autosensData.activeCarbsList = new ArrayList<>();
|
||||||
|
|
||||||
|
//console.error(bgTime , bucketed_data[i].glucose);
|
||||||
|
double bg;
|
||||||
|
double avgDelta;
|
||||||
|
double delta;
|
||||||
|
bg = bucketed_data.get(i).value;
|
||||||
|
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
|
||||||
|
log.error("! value < 39");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
delta = (bg - bucketed_data.get(i + 1).value);
|
||||||
|
|
||||||
|
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
|
||||||
|
|
||||||
|
double bgi = -iob.activity * sens * 5;
|
||||||
|
double deviation = delta - bgi;
|
||||||
|
|
||||||
|
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
||||||
|
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
||||||
|
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
|
||||||
|
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if we are absorbing carbs
|
||||||
|
if (previous != null && previous.cob > 0) {
|
||||||
|
// calculate sum of min carb impact from all active treatments
|
||||||
|
double totalMinCarbsImpact = 0d;
|
||||||
|
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
||||||
|
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
||||||
|
totalMinCarbsImpact += c.min5minCarbImpact;
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out how many carbs that represents
|
||||||
|
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
|
||||||
|
double ci = Math.max(deviation, totalMinCarbsImpact);
|
||||||
|
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
|
||||||
|
// and add that to the running total carbsAbsorbed
|
||||||
|
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
|
||||||
|
autosensData.substractAbosorbedCarbs();
|
||||||
|
}
|
||||||
|
autosensData.removeOldCarbs(bgTime);
|
||||||
|
autosensData.cob += autosensData.carbsFromBolus;
|
||||||
|
autosensData.deviation = deviation;
|
||||||
|
autosensData.bgi = bgi;
|
||||||
|
autosensData.delta = delta;
|
||||||
|
|
||||||
|
// calculate autosens only without COB
|
||||||
|
if (autosensData.cob <= 0) {
|
||||||
|
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
|
||||||
|
autosensData.pastSensitivity += "=";
|
||||||
|
autosensData.nonEqualDeviation = true;
|
||||||
|
} else if (deviation > 0) {
|
||||||
|
autosensData.pastSensitivity += "+";
|
||||||
|
autosensData.nonEqualDeviation = true;
|
||||||
|
} else {
|
||||||
|
autosensData.pastSensitivity += "-";
|
||||||
|
autosensData.nonEqualDeviation = true;
|
||||||
|
}
|
||||||
|
autosensData.nonCarbsDeviation = true;
|
||||||
|
} else {
|
||||||
|
autosensData.pastSensitivity += "C";
|
||||||
|
}
|
||||||
|
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
||||||
|
|
||||||
|
previous = autosensData;
|
||||||
|
autosensDataTable.put(bgTime, autosensData);
|
||||||
|
autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
|
||||||
|
if (Config.logAutosensData)
|
||||||
|
log.debug(autosensData.log(bgTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventAutosensCalculationFinished());
|
||||||
|
log.debug("Finishing calculation thread: " + from);
|
||||||
|
} finally {
|
||||||
|
mWakeLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
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.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
@ -191,8 +192,10 @@ public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{
|
||||||
log.debug(ratioLimit);
|
log.debug(ratioLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio);
|
if (Config.logAutosensData) {
|
||||||
|
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio + " mealCOB: " + current.cob);
|
||||||
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations));
|
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations));
|
||||||
|
}
|
||||||
|
|
||||||
AutosensResult output = new AutosensResult();
|
AutosensResult output = new AutosensResult();
|
||||||
output.ratio = Round.roundTo(ratio, 0.01);
|
output.ratio = Round.roundTo(ratio, 0.01);
|
||||||
|
|
|
@ -7,8 +7,10 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
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.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
@ -118,7 +120,7 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface
|
||||||
return new AutosensResult();
|
return new AutosensResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
AutosensData current = IobCobCalculatorPlugin.getLastAutosensData("SensitivityOref0"); // this is running inside lock already
|
AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
log.debug("No current autosens data available");
|
log.debug("No current autosens data available");
|
||||||
return new AutosensResult();
|
return new AutosensResult();
|
||||||
|
@ -199,10 +201,8 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface
|
||||||
log.debug(ratioLimit);
|
log.debug(ratioLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
double newisf = Math.round(Profile.toMgdl(sens, profile.getUnits()) / ratio);
|
if (Config.logAutosensData)
|
||||||
if (ratio != 1) {
|
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " ratio: " + ratio + " mealCOB: " + current.cob);
|
||||||
log.debug("ISF adjusted from " + Profile.toMgdl(sens, profile.getUnits()) + " to " + newisf);
|
|
||||||
}
|
|
||||||
|
|
||||||
AutosensResult output = new AutosensResult();
|
AutosensResult output = new AutosensResult();
|
||||||
output.ratio = Round.roundTo(ratio, 0.01);
|
output.ratio = Round.roundTo(ratio, 0.01);
|
||||||
|
|
|
@ -217,7 +217,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio);
|
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio + " mealCOB: " + current.cob);
|
||||||
|
|
||||||
AutosensResult output = new AutosensResult();
|
AutosensResult output = new AutosensResult();
|
||||||
output.ratio = Round.roundTo(ratio, 0.01);
|
output.ratio = Round.roundTo(ratio, 0.01);
|
||||||
|
|
Loading…
Reference in a new issue