Search in sources :

Example 1 with CalibrationAbstract

use of com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract in project xDrip by NightscoutFoundation.

the class Home method extraStatusLine.

@NonNull
public static String extraStatusLine() {
    final StringBuilder extraline = new StringBuilder();
    final Calibration lastCalibration = Calibration.lastValid();
    if (Pref.getBoolean("status_line_calibration_long", false) && lastCalibration != null) {
        if (extraline.length() != 0)
            extraline.append(' ');
        extraline.append("slope = ");
        extraline.append(String.format("%.2f", lastCalibration.slope));
        extraline.append(' ');
        extraline.append("inter = ");
        extraline.append(String.format("%.2f", lastCalibration.intercept));
    }
    if (Pref.getBoolean("status_line_calibration_short", false) && lastCalibration != null) {
        if (extraline.length() != 0)
            extraline.append(' ');
        extraline.append("s:");
        extraline.append(String.format("%.2f", lastCalibration.slope));
        extraline.append(' ');
        extraline.append("i:");
        extraline.append(String.format("%.2f", lastCalibration.intercept));
    }
    if (Pref.getBoolean("status_line_avg", false) || Pref.getBoolean("status_line_a1c_dcct", false) || Pref.getBoolean("status_line_a1c_ifcc", false) || Pref.getBoolean("status_line_in", false) || Pref.getBoolean("status_line_high", false) || Pref.getBoolean("status_line_low", false) || Pref.getBoolean("status_line_stdev", false) || Pref.getBoolean("status_line_carbs", false) || Pref.getBoolean("status_line_insulin", false) || Pref.getBoolean("status_line_royce_ratio", false) || Pref.getBoolean("status_line_accuracy", false) || Pref.getBoolean("status_line_capture_percentage", false) || Pref.getBoolean("status_line_pump_reservoir", false)) {
        final StatsResult statsResult = new StatsResult(Pref.getInstance(), Pref.getBooleanDefaultFalse("extra_status_stats_24h"));
        if (Pref.getBoolean("status_line_avg", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getAverageUnitised());
        }
        if (Pref.getBoolean("status_line_a1c_dcct", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getA1cDCCT());
        }
        if (Pref.getBoolean("status_line_a1c_ifcc", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getA1cIFCC());
        }
        if (Pref.getBoolean("status_line_in", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getInPercentage());
        }
        if (Pref.getBoolean("status_line_high", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getHighPercentage());
        }
        if (Pref.getBoolean("status_line_low", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getLowPercentage());
        }
        if (Pref.getBoolean("status_line_stdev", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getStdevUnitised());
        }
        if (Pref.getBoolean("status_line_carbs", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            // extraline.append("Carbs: " + statsResult.getTotal_carbs());
            extraline.append("Carbs:" + Math.round(statsResult.getTotal_carbs()));
        }
        if (Pref.getBoolean("status_line_insulin", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append("U:" + JoH.qs(statsResult.getTotal_insulin(), 2));
        }
        if (Pref.getBoolean("status_line_royce_ratio", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append("C/I:" + JoH.qs(statsResult.getRatio(), 2));
        }
        if (Pref.getBoolean("status_line_capture_percentage", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(statsResult.getCapturePercentage(false));
        }
        if (Pref.getBoolean("status_line_accuracy", false)) {
            final long accuracy_period = DAY_IN_MS * 3;
            if (extraline.length() != 0)
                extraline.append(' ');
            final String accuracy_report = Accuracy.evaluateAccuracy(accuracy_period);
            if ((accuracy_report != null) && (accuracy_report.length() > 0)) {
                extraline.append(accuracy_report);
            } else {
                final String accuracy = BloodTest.evaluateAccuracy(accuracy_period);
                extraline.append(((accuracy != null) ? " " + accuracy : ""));
            }
        }
        if (Pref.getBoolean("status_line_pump_reservoir", false)) {
            if (extraline.length() != 0)
                extraline.append(' ');
            extraline.append(PumpStatus.getBolusIoBString());
            extraline.append(PumpStatus.getReservoirString());
            extraline.append(PumpStatus.getBatteryString());
        }
    }
    if (Pref.getBoolean("extra_status_calibration_plugin", false)) {
        // make sure do this only once
        final CalibrationAbstract plugin = getCalibrationPluginFromPreferences();
        if (plugin != null) {
            final CalibrationAbstract.CalibrationData pcalibration = plugin.getCalibrationData();
            // not tested on the widget yet
            if (extraline.length() > 0)
                extraline.append("\n");
            if (pcalibration != null)
                extraline.append("(" + plugin.getAlgorithmName() + ") s:" + JoH.qs(pcalibration.slope, 2) + " i:" + JoH.qs(pcalibration.intercept, 2));
            BgReading bgReading = BgReading.last();
            if (bgReading != null) {
                final boolean doMgdl = Pref.getString("units", "mgdl").equals("mgdl");
                extraline.append(" \u21D2 " + BgGraphBuilder.unitized_string(plugin.getGlucoseFromSensorValue(bgReading.age_adjusted_raw_value), doMgdl) + " " + BgGraphBuilder.unit(doMgdl));
            }
        }
        // If we are using the plugin as the primary then show xdrip original as well
        if (Pref.getBooleanDefaultFalse("display_glucose_from_plugin") || Pref.getBooleanDefaultFalse("use_pluggable_alg_as_primary")) {
            // make sure do this only once
            final CalibrationAbstract plugin_xdrip = getCalibrationPlugin(PluggableCalibration.Type.xDripOriginal);
            if (plugin_xdrip != null) {
                final CalibrationAbstract.CalibrationData pcalibration = plugin_xdrip.getCalibrationData();
                if (extraline.length() > 0)
                    // not tested on the widget yet
                    extraline.append("\n");
                if (pcalibration != null)
                    extraline.append("(" + plugin_xdrip.getAlgorithmName() + ") s:" + JoH.qs(pcalibration.slope, 2) + " i:" + JoH.qs(pcalibration.intercept, 2));
                BgReading bgReading = BgReading.last();
                if (bgReading != null) {
                    final boolean doMgdl = Pref.getString("units", "mgdl").equals("mgdl");
                    extraline.append(" \u21D2 " + BgGraphBuilder.unitized_string(plugin_xdrip.getGlucoseFromSensorValue(bgReading.age_adjusted_raw_value), doMgdl) + " " + BgGraphBuilder.unit(doMgdl));
                }
            }
        }
    }
    if (Pref.getBoolean("status_line_time", false)) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        if (extraline.length() != 0)
            extraline.append(' ');
        extraline.append(sdf.format(new Date()));
    }
    return extraline.toString();
}
Also used : CalibrationAbstract(com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract) Calibration(com.eveningoutpost.dexdrip.Models.Calibration) PluggableCalibration(com.eveningoutpost.dexdrip.calibrations.PluggableCalibration) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) SimpleDateFormat(java.text.SimpleDateFormat) StatsResult(com.eveningoutpost.dexdrip.stats.StatsResult) Date(java.util.Date) NonNull(android.support.annotation.NonNull)

Example 2 with CalibrationAbstract

use of com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract in project xDrip by NightscoutFoundation.

the class BestGlucose method getDisplayGlucose.

// note we don't support the original depreciated "predictive" mode
// TODO stale data
// TODO time ago
// TODO check BGgraph data is current
// TODO internalize delta handling to handle irregular periods and missing data plugins etc
// TODO see getSlopeArrowSymbolBeforeCalibration for calculation method for arbitary slope
// TODO option to process noise or not
// TODO check what happens if there is only a single entry, especially regarding delta
// TODO select by time
public static DisplayGlucose getDisplayGlucose() {
    if (prefs == null)
        prefs = PreferenceManager.getDefaultSharedPreferences(xdrip.getAppContext());
    // return value
    final DisplayGlucose dg = new DisplayGlucose();
    final boolean doMgdl = (prefs.getString("units", "mgdl").equals("mgdl"));
    final boolean is_follower = Home.get_follower();
    dg.doMgDl = doMgdl;
    List<BgReading> last_2 = BgReading.latest(2);
    final BgReading lastBgReading = BgReading.last(is_follower);
    if (lastBgReading == null)
        return null;
    final CalibrationAbstract.CalibrationData pcalibration;
    final CalibrationAbstract plugin = getCalibrationPluginFromPreferences();
    double estimate = -1;
    double filtered = -1;
    long timestamp = -1;
    double previous_estimate = -1;
    double previous_filtered = -1;
    long previous_timestamp = -1;
    // normal first
    estimate = lastBgReading.calculated_value;
    filtered = lastBgReading.filtered_calculated_value;
    timestamp = lastBgReading.timestamp;
    if (last_2.size() == 2) {
        previous_estimate = last_2.get(1).calculated_value;
        previous_filtered = last_2.get(1).filtered_calculated_value;
        previous_timestamp = last_2.get(1).timestamp;
    }
    dg.mssince = JoH.msSince(lastBgReading.timestamp);
    dg.timestamp = lastBgReading.timestamp;
    // if we are actively using a plugin, get the glucose calculation from there
    if ((plugin != null) && ((pcalibration = plugin.getCalibrationData()) != null) && (Pref.getBoolean("display_glucose_from_plugin", false))) {
        dg.plugin_name = plugin.getAlgorithmName();
        Log.d(TAG, "Using plugin: " + dg.plugin_name);
        dg.from_plugin = true;
        estimate = plugin.getGlucoseFromBgReading(lastBgReading, pcalibration);
        filtered = plugin.getGlucoseFromFilteredBgReading(lastBgReading, pcalibration);
        // also try to update the previous values in the same way
        if (last_2.size() == 2) {
            previous_estimate = plugin.getGlucoseFromBgReading(last_2.get(1), pcalibration);
            previous_filtered = plugin.getGlucoseFromFilteredBgReading(last_2.get(1), pcalibration);
        }
    }
    int warning_level = 0;
    String slope_arrow = "";
    String slope_name = "";
    String extrastring = "";
    double estimated_delta = 0;
    // TODO refresh bggraph if needed based on cache - observe
    // should this be conditional on whether bg_compensate_noise is set?
    BgGraphBuilder.refreshNoiseIfOlderThan(dg.timestamp);
    dg.noise = BgGraphBuilder.last_noise;
    boolean bg_from_filtered = prefs.getBoolean("bg_from_filtered", false);
    // if noise has settled down then switch off filtered mode
    if ((bg_from_filtered) && (BgGraphBuilder.last_noise < BgGraphBuilder.NOISE_FORGIVE) && (prefs.getBoolean("bg_compensate_noise", false))) {
        bg_from_filtered = false;
        prefs.edit().putBoolean("bg_from_filtered", false).apply();
    }
    // TODO Noise uses plugin in bggraphbuilder
    if (compensateNoise()) {
        // this maybe needs scaling based on noise intensity
        estimate = BgGraphBuilder.best_bg_estimate;
        estimated_delta = BgGraphBuilder.best_bg_estimate - BgGraphBuilder.last_bg_estimate;
        // TODO handle ratio when period is not dexcom period?
        double estimated_delta_by_minute = estimated_delta / (BgGraphBuilder.DEXCOM_PERIOD / 60000);
        dg.slope = estimated_delta_by_minute / 60000;
        dg.unitized_delta_no_units = BgGraphBuilder.unitizedDeltaStringRaw(false, true, estimated_delta, doMgdl);
        // TODO optimize adding units
        dg.unitized_delta = BgGraphBuilder.unitizedDeltaStringRaw(true, true, estimated_delta, doMgdl);
        // delta by minute
        slope_arrow = BgReading.slopeToArrowSymbol(estimated_delta_by_minute);
        slope_name = BgReading.slopeName(estimated_delta_by_minute);
        // warning symbol !
        extrastring = "\u26A0";
        warning_level = 1;
        if ((BgGraphBuilder.last_noise > BgGraphBuilder.NOISE_HIGH) && (DexCollectionType.hasFiltered())) {
            // force filtered mode
            bg_from_filtered = true;
        }
    } else {
        // TODO ignores plugin
        // dg.unitized_delta = BgGraphBuilder.unitizedDeltaString(true, true, is_follower , doMgdl);
        dg.unitized_delta_no_units = unitizedDeltaString(false, true, doMgdl, estimate, timestamp, previous_estimate, previous_timestamp);
        // TODO time stretch adjustment?
        estimated_delta = estimate - previous_estimate;
        // TODO optimize adding units
        dg.unitized_delta = unitizedDeltaString(true, true, doMgdl, estimate, timestamp, previous_estimate, previous_timestamp);
        long time_delta = timestamp - previous_timestamp;
        if (time_delta < 0)
            Log.wtf(TAG, "Time delta is negative! : " + time_delta);
        // slope_arrow = lastBgReading.slopeArrow(); // internalize this for plugins
        double slope = calculateSlope(estimate, timestamp, previous_estimate, previous_timestamp);
        dg.slope = slope;
        // slope by minute
        slope_arrow = BgReading.slopeToArrowSymbol(slope * 60000);
        slope_name = BgReading.slopeName(slope * 60000);
        Log.d(TAG, "No noise option slope by minute: " + JoH.qs(slope * 60000, 5));
    }
    // TODO bit more work on deltas etc needed here
    if (bg_from_filtered) {
        estimate = filtered;
        warning_level = 2;
    }
    dg.unitized_value = BgGraphBuilder.unitized(estimate, doMgdl);
    final String stringEstimate = BgGraphBuilder.unitized_string(estimate, doMgdl);
    if ((lastBgReading.hide_slope) || (bg_from_filtered)) {
        slope_arrow = "";
        slope_name = "NOT COMPUTABLE";
    }
    dg.mgdl = estimate;
    dg.delta_mgdl = estimated_delta;
    dg.warning = warning_level;
    dg.unitized = stringEstimate;
    dg.delta_arrow = slope_arrow;
    dg.extra_string = extrastring;
    dg.delta_name = slope_name;
    // to be moved one day
    if (!SensorSanity.isRawValueSane(lastBgReading.raw_data)) {
        dg.delta_arrow = "!";
        dg.unitized = ">!?";
        dg.mgdl = 0;
        dg.delta_mgdl = 0;
        dg.unitized_value = 0;
        dg.unitized_delta = "";
        dg.slope = 0;
        if (JoH.ratelimit("exceeding_max_raw", 120)) {
            UserError.Log.wtf(TAG, "Failing raw bounds validation: " + lastBgReading.raw_data);
        }
    }
    if (d)
        Log.d(TAG, "dg result: " + dg.unitized + " previous: " + BgGraphBuilder.unitized_string(previous_estimate, doMgdl));
    return dg;
}
Also used : CalibrationAbstract(com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) SpannableString(android.text.SpannableString)

Example 3 with CalibrationAbstract

use of com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract in project xDrip by NightscoutFoundation.

the class CalibrationGraph method setupCharts.

public void setupCharts() {
    chart = (LineChartView) findViewById(R.id.chart);
    List<Line> lines = new ArrayList<Line>();
    // calibration values
    List<Calibration> calibrations = Calibration.allForSensor();
    List<Line> greyLines = getCalibrationsLine(calibrations, Color.parseColor("#66FFFFFF"));
    calibrations = Calibration.allForSensorInLastFourDays();
    List<Line> blueLines = getCalibrationsLine(calibrations, ChartUtils.COLOR_BLUE);
    Calibration calibration = Calibration.lastValid();
    if (calibration != null) {
        // set header
        DecimalFormat df = new DecimalFormat("#");
        df.setMaximumFractionDigits(2);
        df.setMinimumFractionDigits(2);
        String Header = "slope = " + df.format(calibration.slope) + " intercept = " + df.format(calibration.intercept);
        GraphHeader.setText(Header);
        // red line
        List<PointValue> lineValues = new ArrayList<PointValue>();
        final float conversion_factor = (float) (doMgdl ? 1 : Constants.MGDL_TO_MMOLL);
        lineValues.add(new PointValue((float) start_x, (conversion_factor * (float) (start_x * calibration.slope + calibration.intercept))));
        lineValues.add(new PointValue((float) end_x, (conversion_factor * (float) (end_x * calibration.slope + calibration.intercept))));
        Line calibrationLine = new Line(lineValues);
        calibrationLine.setColor(ChartUtils.COLOR_RED);
        calibrationLine.setHasLines(true);
        calibrationLine.setHasPoints(false);
        lines.add(calibrationLine);
        // calibration plugin
        final CalibrationAbstract plugin = getCalibrationPluginFromPreferences();
        if (plugin != null) {
            final CalibrationAbstract.CalibrationData pcalibration = plugin.getCalibrationData();
            final List<PointValue> plineValues = new ArrayList<PointValue>();
            plineValues.add(new PointValue((float) start_x, (conversion_factor * (float) (plugin.getGlucoseFromSensorValue(start_x, pcalibration)))));
            plineValues.add(new PointValue((float) end_x, (conversion_factor * (float) (plugin.getGlucoseFromSensorValue(end_x, pcalibration)))));
            final Line pcalibrationLine = new Line(plineValues);
            pcalibrationLine.setColor(Color.parseColor(plugin_color));
            pcalibrationLine.setHasLines(true);
            pcalibrationLine.setHasPoints(false);
            lines.add(pcalibrationLine);
            PluginHeader.setText("(" + plugin.getAlgorithmName() + ")  " + "s = " + df.format(pcalibration.slope) + "  i = " + df.format(pcalibration.intercept));
            PluginHeader.setTextColor(Color.parseColor(plugin_color));
        }
        // add lines in order
        for (Line greyLine : greyLines) {
            lines.add(greyLine);
        }
        for (Line blueLine : blueLines) {
            lines.add(blueLine);
        }
    }
    Axis axisX = new Axis();
    Axis axisY = new Axis().setHasLines(true);
    axisX.setName("Raw Value");
    axisY.setName("Glucose " + (doMgdl ? "mg/dl" : "mmol/l"));
    data = new LineChartData(lines);
    data.setAxisXBottom(axisX);
    data.setAxisYLeft(axisY);
    chart.setLineChartData(data);
}
Also used : PointValue(lecho.lib.hellocharts.model.PointValue) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) Calibration(com.eveningoutpost.dexdrip.Models.Calibration) Line(lecho.lib.hellocharts.model.Line) CalibrationAbstract(com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract) LineChartData(lecho.lib.hellocharts.model.LineChartData) Axis(lecho.lib.hellocharts.model.Axis)

Example 4 with CalibrationAbstract

use of com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract in project xDrip by NightscoutFoundation.

the class BloodTest method opportunisticCalibration.

static synchronized void opportunisticCalibration() {
    if (Pref.getBooleanDefaultFalse("bluetooth_meter_for_calibrations_auto")) {
        final BloodTest bt = lastValid();
        if (bt == null) {
            Log.d(TAG, "opportunistic: No blood tests");
            return;
        }
        if (JoH.msSince(bt.timestamp) > Constants.DAY_IN_MS) {
            Log.d(TAG, "opportunistic: Blood test older than 1 days ago");
            return;
        }
        if ((bt.uuid == null) || (bt.uuid.length() < 8)) {
            Log.d(TAG, "opportunisitic: invalid uuid");
            return;
        }
        if ((bt.uuid != null) && (bt.uuid.length() > 1) && PersistentStore.getString(LAST_BT_AUTO_CALIB_UUID).equals(bt.uuid)) {
            Log.d(TAG, "opportunistic: Already processed uuid: " + bt.uuid);
            return;
        }
        final Calibration calibration = Calibration.lastValid();
        if (calibration == null) {
            Log.d(TAG, "opportunistic: No calibrations");
            return;
        }
        if (JoH.msSince(calibration.timestamp) < Constants.HOUR_IN_MS) {
            Log.d(TAG, "opportunistic: Last calibration less than 1 hour ago");
            return;
        }
        if (bt.timestamp <= calibration.timestamp) {
            Log.d(TAG, "opportunistic: Blood test isn't more recent than last calibration");
            return;
        }
        // get closest bgreading - must be within dexcom period and locked to sensor
        final BgReading bgReading = BgReading.getForPreciseTimestamp(bt.timestamp + (AddCalibration.estimatedInterstitialLagSeconds * 1000), BgGraphBuilder.DEXCOM_PERIOD);
        if (bgReading == null) {
            Log.d(TAG, "opportunistic: No matching bg reading");
            return;
        }
        if (bt.timestamp > highest_timestamp) {
            Accuracy.create(bt, bgReading, "xDrip Original");
            final CalibrationAbstract plugin = PluggableCalibration.getCalibrationPluginFromPreferences();
            final CalibrationAbstract.CalibrationData cd = (plugin != null) ? plugin.getCalibrationData(bgReading.timestamp) : null;
            if (plugin != null) {
                BgReading pluginBgReading = plugin.getBgReadingFromBgReading(bgReading, cd);
                Accuracy.create(bt, pluginBgReading, plugin.getAlgorithmName());
            }
            highest_timestamp = bt.timestamp;
        }
        if (!CalibrationRequest.isSlopeFlatEnough(bgReading)) {
            Log.d(TAG, "opportunistic: Slope is not flat enough at: " + JoH.dateTimeText(bgReading.timestamp));
            return;
        }
        // TODO store evaluation failure for this record in cache for future optimization
        // TODO Check we have prior reading as well perhaps
        UserError.Log.ueh(TAG, "Opportunistic calibration for Blood Test at " + JoH.dateTimeText(bt.timestamp) + " of " + BgGraphBuilder.unitized_string_with_units_static(bt.mgdl) + " matching sensor slope at: " + JoH.dateTimeText(bgReading.timestamp));
        final long time_since = JoH.msSince(bt.timestamp);
        Log.d(TAG, "opportunistic: attempting auto calibration");
        PersistentStore.setString(LAST_BT_AUTO_CALIB_UUID, bt.uuid);
        Home.startHomeWithExtra(xdrip.getAppContext(), Home.BLUETOOTH_METER_CALIBRATION, BgGraphBuilder.unitized_string_static(bt.mgdl), Long.toString(time_since), "auto");
    }
}
Also used : CalibrationAbstract(com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract) PluggableCalibration(com.eveningoutpost.dexdrip.calibrations.PluggableCalibration) AddCalibration(com.eveningoutpost.dexdrip.AddCalibration)

Example 5 with CalibrationAbstract

use of com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract in project xDrip-plus by jamorham.

the class BloodTest method opportunisticCalibration.

static synchronized void opportunisticCalibration() {
    if (Pref.getBooleanDefaultFalse("bluetooth_meter_for_calibrations_auto")) {
        final BloodTest bt = lastValid();
        if (bt == null) {
            Log.d(TAG, "opportunistic: No blood tests");
            return;
        }
        if (JoH.msSince(bt.timestamp) > Constants.DAY_IN_MS) {
            Log.d(TAG, "opportunistic: Blood test older than 1 days ago");
            return;
        }
        if ((bt.uuid == null) || (bt.uuid.length() < 8)) {
            Log.d(TAG, "opportunisitic: invalid uuid");
            return;
        }
        if ((bt.uuid != null) && (bt.uuid.length() > 1) && PersistentStore.getString(LAST_BT_AUTO_CALIB_UUID).equals(bt.uuid)) {
            Log.d(TAG, "opportunistic: Already processed uuid: " + bt.uuid);
            return;
        }
        final Calibration calibration = Calibration.lastValid();
        if (calibration == null) {
            Log.d(TAG, "opportunistic: No calibrations");
            return;
        }
        if (JoH.msSince(calibration.timestamp) < Constants.HOUR_IN_MS) {
            Log.d(TAG, "opportunistic: Last calibration less than 1 hour ago");
            return;
        }
        if (bt.timestamp <= calibration.timestamp) {
            Log.d(TAG, "opportunistic: Blood test isn't more recent than last calibration");
            return;
        }
        // get closest bgreading - must be within dexcom period and locked to sensor
        final BgReading bgReading = BgReading.getForPreciseTimestamp(bt.timestamp + (AddCalibration.estimatedInterstitialLagSeconds * 1000), BgGraphBuilder.DEXCOM_PERIOD);
        if (bgReading == null) {
            Log.d(TAG, "opportunistic: No matching bg reading");
            return;
        }
        if (bt.timestamp > highest_timestamp) {
            Accuracy.create(bt, bgReading, "xDrip Original");
            final CalibrationAbstract plugin = PluggableCalibration.getCalibrationPluginFromPreferences();
            final CalibrationAbstract.CalibrationData cd = (plugin != null) ? plugin.getCalibrationData(bgReading.timestamp) : null;
            if (plugin != null) {
                BgReading pluginBgReading = plugin.getBgReadingFromBgReading(bgReading, cd);
                Accuracy.create(bt, pluginBgReading, plugin.getAlgorithmName());
            }
            highest_timestamp = bt.timestamp;
        }
        if (!CalibrationRequest.isSlopeFlatEnough(bgReading)) {
            Log.d(TAG, "opportunistic: Slope is not flat enough at: " + JoH.dateTimeText(bgReading.timestamp));
            return;
        }
        // TODO store evaluation failure for this record in cache for future optimization
        // TODO Check we have prior reading as well perhaps
        UserError.Log.ueh(TAG, "Opportunistic calibration for Blood Test at " + JoH.dateTimeText(bt.timestamp) + " of " + BgGraphBuilder.unitized_string_with_units_static(bt.mgdl) + " matching sensor slope at: " + JoH.dateTimeText(bgReading.timestamp));
        final long time_since = JoH.msSince(bt.timestamp);
        Log.d(TAG, "opportunistic: attempting auto calibration");
        PersistentStore.setString(LAST_BT_AUTO_CALIB_UUID, bt.uuid);
        Home.startHomeWithExtra(xdrip.getAppContext(), Home.BLUETOOTH_METER_CALIBRATION, BgGraphBuilder.unitized_string_static(bt.mgdl), Long.toString(time_since), "auto");
    }
}
Also used : CalibrationAbstract(com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract) PluggableCalibration(com.eveningoutpost.dexdrip.calibrations.PluggableCalibration) AddCalibration(com.eveningoutpost.dexdrip.AddCalibration)

Aggregations

CalibrationAbstract (com.eveningoutpost.dexdrip.calibrations.CalibrationAbstract)12 PluggableCalibration (com.eveningoutpost.dexdrip.calibrations.PluggableCalibration)8 AddCalibration (com.eveningoutpost.dexdrip.AddCalibration)6 BgReading (com.eveningoutpost.dexdrip.Models.BgReading)6 Calibration (com.eveningoutpost.dexdrip.Models.Calibration)6 ArrayList (java.util.ArrayList)6 DecimalFormat (java.text.DecimalFormat)4 Date (java.util.Date)4 PointValue (lecho.lib.hellocharts.model.PointValue)4 NonNull (android.support.annotation.NonNull)2 SpannableString (android.text.SpannableString)2 BloodTest (com.eveningoutpost.dexdrip.Models.BloodTest)2 Forecast (com.eveningoutpost.dexdrip.Models.Forecast)2 PolyTrendLine (com.eveningoutpost.dexdrip.Models.Forecast.PolyTrendLine)2 TrendLine (com.eveningoutpost.dexdrip.Models.Forecast.TrendLine)2 Iob (com.eveningoutpost.dexdrip.Models.Iob)2 Treatments (com.eveningoutpost.dexdrip.Models.Treatments)2 StatsResult (com.eveningoutpost.dexdrip.stats.StatsResult)2 SimpleDateFormat (java.text.SimpleDateFormat)2 Matcher (java.util.regex.Matcher)2