Merge pull request #46 from MilosKozak/dev

update from Milos dev
This commit is contained in:
AdrianLxM 2017-01-17 21:30:48 +01:00 committed by GitHub
commit 58282e23ee
115 changed files with 59189 additions and 658 deletions

View file

@ -37,7 +37,7 @@
<ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" /> <ConfirmationsSetting value="0" id="Remove" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View file

@ -0,0 +1,61 @@
'use strict';
function reason(rT, msg) {
rT.reason = (rT.reason ? rT.reason + '. ' : '') + msg;
console.error(msg);
}
var tempBasalFunctions = {};
tempBasalFunctions.getMaxSafeBasal = function getMaxSafeBasal(profile) {
var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
};
tempBasalFunctions.setTempBasal = function setTempBasal(rate, duration, profile, rT, currenttemp) {
//var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
var round_basal = require('./round-basal');
if (rate < 0) {
rate = 0;
} // if >30m @ 0 required, zero temp will be extended to 30m instead
else if (rate > maxSafeBasal) {
rate = maxSafeBasal;
}
var suggestedRate = round_basal(rate, profile);
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > 20 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8) {
rT.reason += ", but "+currenttemp.duration+"m left and " + currenttemp.rate + " ~ req " + suggestedRate + "U/hr: no action required";
return rT;
}
if (suggestedRate === profile.current_basal) {
if (profile.skip_neutral_temps) {
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && currenttemp.duration > 0) {
reason(rT, 'Suggested rate is same as profile rate, a temp basal is active, canceling current temp');
rT.duration = 0;
rT.rate = 0;
return rT;
} else {
reason(rT, 'Suggested rate is same as profile rate, no temp basal is active, doing nothing');
return rT;
}
} else {
reason(rT, 'Setting neutral temp basal of ' + profile.current_basal + 'U/hr');
rT.duration = duration;
rT.rate = suggestedRate;
return rT;
}
} else {
rT.duration = duration;
rT.rate = suggestedRate;
return rT;
}
};
module.exports = tempBasalFunctions;

View file

@ -0,0 +1,487 @@
/*
Determine Basal
Released under MIT license. See the accompanying LICENSE.txt file for
full terms and conditions
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var round_basal = require('../round-basal')
// Rounds value to 'digits' decimal places
function round(value, digits)
{
var scale = Math.pow(10, digits);
return Math.round(value * scale) / scale;
}
// we expect BG to rise or fall at the rate of BGI,
// adjusted by the rate at which BG would need to rise /
// fall to get eventualBG to target over DIA/2 hours
function calculate_expected_delta(dia, target_bg, eventual_bg, bgi) {
// (hours * mins_per_hour) / 5 = how many 5 minute periods in dia/2
var dia_in_5min_blocks = (dia/2 * 60) / 5;
var target_delta = target_bg - eventual_bg;
var expectedDelta = round(bgi + (target_delta / dia_in_5min_blocks), 1);
return expectedDelta;
}
function convert_bg(value, profile)
{
if (profile.out_units == "mmol/L")
{
return round(value / 18, 1).toFixed(1);
}
else
{
return value.toFixed(0);
}
}
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions) {
var rT = { //short for requestedTemp
};
if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') {
rT.error ='Error: could not get current basal rate';
return rT;
}
var basal = profile.current_basal;
if (typeof autosens_data !== 'undefined' ) {
basal = profile.current_basal * autosens_data.ratio;
basal = round_basal(basal, profile);
if (basal != profile.current_basal) {
console.error("Adjusting basal from "+profile.current_basal+" to "+basal);
}
}
var bg = glucose_status.glucose;
// TODO: figure out how to use raw isig data to estimate BG
if (bg < 39) { //Dexcom is in ??? mode or calibrating
rT.reason = "CGM is calibrating or in ??? state";
if (basal <= currenttemp.rate * 1.2) { // high temp is running
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
} else { //do nothing.
rT.reason += ", temp " + currenttemp.rate + " <~ current basal " + basal + "U/hr";
return rT;
}
}
var max_iob = profile.max_iob; // maximum amount of non-bolus IOB OpenAPS will ever deliver
// if target_bg is set, great. otherwise, if min and max are set, then set target to their average
var target_bg;
var min_bg;
var max_bg;
if (typeof profile.min_bg !== 'undefined') {
min_bg = profile.min_bg;
}
if (typeof profile.max_bg !== 'undefined') {
max_bg = profile.max_bg;
}
if (typeof profile.target_bg !== 'undefined') {
target_bg = profile.target_bg;
} else {
if (typeof profile.min_bg !== 'undefined' && typeof profile.max_bg !== 'undefined') {
target_bg = (profile.min_bg + profile.max_bg) / 2;
} else {
rT.error ='Error: could not determine target_bg';
return rT;
}
}
// adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120
if (typeof autosens_data !== 'undefined' && profile.autosens_adjust_targets) {
if (profile.temptargetSet) {
console.error("Temp Target set, not adjusting with autosens");
} else {
min_bg = Math.round((min_bg - 60) / autosens_data.ratio) + 60;
max_bg = Math.round((max_bg - 60) / autosens_data.ratio) + 60;
new_target_bg = Math.round((target_bg - 60) / autosens_data.ratio) + 60;
if (target_bg == new_target_bg) {
console.error("target_bg unchanged:", new_target_bg);
} else {
console.error("Adjusting target_bg from", target_bg, "to", new_target_bg);
}
target_bg = new_target_bg;
}
}
if (typeof iob_data === 'undefined' ) {
rT.error ='Error: iob_data undefined';
return rT;
}
var iobArray = iob_data;
if (typeof(iob_data.length) && iob_data.length > 1) {
iob_data = iobArray[0];
//console.error(JSON.stringify(iob_data[0]));
}
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' ) {
rT.error ='Error: iob_data missing some property';
return rT;
}
var tick;
if (glucose_status.delta > -0.5) {
tick = "+" + round(glucose_status.delta,0);
} else {
tick = round(glucose_status.delta,0);
}
var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
var minAvgDelta = Math.min(glucose_status.short_avgdelta, glucose_status.long_avgdelta);
var sens = profile.sens;
if (typeof autosens_data !== 'undefined' ) {
sens = profile.sens / autosens_data.ratio;
sens = round(sens, 1);
if (sens != profile.sens) {
console.error("Adjusting sens from "+profile.sens+" to "+sens);
}
}
//calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
var bgi = round(( -iob_data.activity * sens * 5 ), 2);
// project deviations for 30 minutes
var deviation = Math.round( 30 / 5 * ( minDelta - bgi ) );
// don't overreact to a big negative delta: use minAvgDelta if deviation is negative
if (deviation < 0) {
deviation = Math.round( (30 / 5) * ( minAvgDelta - bgi ) );
}
// calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
if (iob_data.iob > 0) {
var naive_eventualBG = Math.round( bg - (iob_data.iob * sens) );
} else { // if IOB is negative, be more conservative and use the lower of sens, profile.sens
var naive_eventualBG = Math.round( bg - (iob_data.iob * Math.min(sens, profile.sens) ) );
}
// and adjust it for the deviation above
var eventualBG = naive_eventualBG + deviation;
// calculate what portion of that is due to bolussnooze
var bolusContrib = iob_data.bolussnooze * sens;
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
// adjust that for deviation like we did eventualBG
var snoozeBG = naive_snoozeBG + deviation;
var expectedDelta = calculate_expected_delta(profile.dia, target_bg, eventualBG, bgi);
if (typeof eventualBG === 'undefined' || isNaN(eventualBG)) {
rT.error ='Error: could not calculate eventualBG';
return rT;
}
// min_bg of 90 -> threshold of 70, 110 -> 80, and 130 -> 90
var threshold = min_bg - 0.5*(min_bg-50);
rT = {
'temp': 'absolute'
, 'bg': bg
, 'tick': tick
, 'eventualBG': eventualBG
, 'snoozeBG': snoozeBG
};
var basaliob;
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
// generate predicted future BGs based on IOB, COB, and current absortpion rate
var COBpredBGs = [];
var aCOBpredBGs = [];
var IOBpredBGs = [];
COBpredBGs.push(bg);
aCOBpredBGs.push(bg);
IOBpredBGs.push(bg);
//console.error(meal_data);
// carb impact and duration are 0 unless changed below
var ci = 0;
var cid = 0;
// calculate current carb absorption rate, and how long to absorb all carbs
// CI = current carb impact on BG in mg/dL/5m
ci = Math.round((minDelta - bgi)*10)/10;
if (meal_data.mealCOB * 2 > meal_data.carbs) {
// set ci to a minimum of 3mg/dL/5m (default) if less than half of carbs have absorbed
ci = Math.max(profile.min_5m_carbimpact, ci);
}
aci = 10;
//5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m)
cid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / ci;
acid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / aci;
console.error("Carb Impact:",ci,"mg/dL per 5m; CI Duration:",Math.round(10*cid/6)/10,"hours");
console.error("Accel. Carb Impact:",aci,"mg/dL per 5m; ACI Duration:",Math.round(10*acid/6)/10,"hours");
var minPredBG = 999;
var maxPredBG = bg;
var eventualPredBG = bg;
try {
iobArray.forEach(function(iobTick) {
//console.error(iobTick);
predBGI = round(( -iobTick.activity * sens * 5 ), 2);
// predicted deviation impact drops linearly from current deviation down to zero
// over 60 minutes (data points every 5m)
predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) );
IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI + predDev;
//IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI;
// predicted carb impact drops linearly from current carb impact down to zero
// eventually accounting for all carbs (if they can be absorbed over DIA)
predCI = Math.max(0, ci * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) );
predACI = Math.max(0, aci * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) );
COBpredBG = COBpredBGs[COBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predCI;
aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI;
//console.error(predBGI, predCI, predBG);
IOBpredBGs.push(IOBpredBG);
COBpredBGs.push(COBpredBG);
aCOBpredBGs.push(aCOBpredBG);
// wait 45m before setting minPredBG
if ( COBpredBGs.length > 9 && (COBpredBG < minPredBG) ) { minPredBG = COBpredBG; }
if ( COBpredBG > maxPredBG ) { maxPredBG = COBpredBG; }
});
// set eventualBG to include effect of carbs
//console.error("PredBGs:",JSON.stringify(predBGs));
} catch (e) {
console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled.");
}
rT.predBGs = {};
IOBpredBGs.forEach(function(p, i, theArray) {
theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
});
for (var i=IOBpredBGs.length-1; i > 12; i--) {
if (IOBpredBGs[i-1] != IOBpredBGs[i]) { break; }
else { IOBpredBGs.pop(); }
}
rT.predBGs.IOB = IOBpredBGs;
if (meal_data.mealCOB > 0) {
aCOBpredBGs.forEach(function(p, i, theArray) {
theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
});
for (var i=aCOBpredBGs.length-1; i > 12; i--) {
if (aCOBpredBGs[i-1] != aCOBpredBGs[i]) { break; }
else { aCOBpredBGs.pop(); }
}
rT.predBGs.aCOB = aCOBpredBGs;
}
if (meal_data.mealCOB > 0 && ci > 0 ) {
COBpredBGs.forEach(function(p, i, theArray) {
theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
});
for (var i=COBpredBGs.length-1; i > 12; i--) {
if (COBpredBGs[i-1] != COBpredBGs[i]) { break; }
else { COBpredBGs.pop(); }
}
rT.predBGs.COB = COBpredBGs;
eventualBG = Math.max(eventualBG, Math.round(COBpredBGs[COBpredBGs.length-1]) );
rT.eventualBG = eventualBG;
minPredBG = Math.min(minPredBG, eventualBG);
// set snoozeBG to minPredBG
snoozeBG = Math.round(Math.max(snoozeBG,minPredBG));
rT.snoozeBG = snoozeBG;
}
rT.COB=meal_data.mealCOB;
rT.IOB=iob_data.iob;
rT.reason="COB: " + meal_data.mealCOB + ", Dev: " + deviation + ", BGI: " + bgi + ", ISF: " + convert_bg(sens, profile) + ", Target: " + convert_bg(target_bg, profile) + "; ";
if (bg < threshold) { // low glucose suspend mode: BG is < ~80
rT.reason += "BG " + convert_bg(bg, profile) + "<" + convert_bg(threshold, profile);
if ((glucose_status.delta <= 0 && minDelta <= 0) || (glucose_status.delta < expectedDelta && minDelta < expectedDelta) || bg < 60 ) {
// BG is still falling / rising slower than predicted
return tempBasalFunctions.setTempBasal(0, 30, profile, rT, currenttemp);
}
if (glucose_status.delta > minDelta) {
rT.reason += ", delta " + glucose_status.delta + ">0";
} else {
rT.reason += ", min delta " + minDelta.toFixed(2) + ">0";
}
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
if (eventualBG < min_bg) { // if eventual BG is below target:
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " < " + convert_bg(min_bg, profile);
// if 5m or 30m avg BG is rising faster than expected delta
if (minDelta > expectedDelta && minDelta > 0) {
if (glucose_status.delta > minDelta) {
rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
} else {
rT.reason += ", but Min. Delta " + minDelta.toFixed(2) + " > Exp. Delta " + expectedDelta;
}
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
if (eventualBG < min_bg) {
// if we've bolused recently, we can snooze until the bolus IOB decays (at double speed)
if (snoozeBG > min_bg) { // if adding back in the bolus contribution BG would be above min
rT.reason += ", bolus snooze: eventual BG range " + convert_bg(eventualBG, profile) + "-" + convert_bg(snoozeBG, profile);
//console.error(currenttemp, basal );
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
} else {
// calculate 30m low-temp required to get projected BG up to target
// use snoozeBG to more gradually ramp in any counteraction of the user's boluses
// multiply by 2 to low-temp faster for increased hypo safety
var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / sens);
if (minDelta < 0 && minDelta > expectedDelta) {
// if we're barely falling, newinsulinReq should be barely negative
rT.reason += ", Snooze BG " + convert_bg(snoozeBG, profile);
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq;
}
// rate required to deliver insulinReq less insulin over 30m:
var rate = basal + (2 * insulinReq);
rate = round_basal(rate, profile);
// if required temp < existing temp basal
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled < insulinReq - basal*0.3) { // if current temp would deliver a lot (30% of basal) less than the required insulin, raise the rate
rT.reason += ", "+currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-" + basal*0.3;
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate >= currenttemp.rate * 0.8)) {
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
return rT;
} else {
rT.reason += ", setting " + rate + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
}
}
}
// if there is a low-temp running, and eventualBG would be below min_bg without it, let it run
if (round_basal(currenttemp.rate, profile) < round_basal(basal, profile) ) {
var lowtempimpact = (currenttemp.rate - basal) * (currenttemp.duration/60) * sens;
var adjEventualBG = eventualBG + lowtempimpact;
if ( adjEventualBG < min_bg ) {
rT.reason += "letting low temp of " + currenttemp.rate + " run.";
return rT;
}
}
// if eventual BG is above min but BG is falling faster than expected Delta
if (minDelta < expectedDelta) {
if (glucose_status.delta < minDelta) {
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Delta " + tick + " < Exp. Delta " + expectedDelta;
} else {
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Min. Delta " + minDelta.toFixed(2) + " < Exp. Delta " + expectedDelta;
}
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
// eventualBG or snoozeBG (from minPredBG) is below max_bg
if (eventualBG < max_bg || snoozeBG < max_bg) {
// if there is a high-temp running and eventualBG > max_bg, let it run
if (eventualBG > max_bg && round_basal(currenttemp.rate, profile) > round_basal(basal, profile) ) {
rT.reason += ", " + eventualBG + " > " + max_bg + ": no action required (letting high temp of " + currenttemp.rate + " run)."
return rT;
}
rT.reason += convert_bg(eventualBG, profile)+"-"+convert_bg(snoozeBG, profile)+" in range: no temp required";
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
}
// eventual BG is at/above target:
// if iob is over max, just cancel any temps
var basaliob;
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " >= " + convert_bg(max_bg, profile) + ", ";
if (basaliob > max_iob) {
rT.reason += "basaliob " + round(basaliob,2) + " > max_iob " + max_iob;
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
}
} else { // otherwise, calculate 30m high-temp required to get projected BG down to target
// insulinReq is the additional insulin required to get down to max bg:
// if in meal assist mode, check if snoozeBG is lower, as eventualBG is not dependent on IOB
var insulinReq = round( (Math.min(snoozeBG,eventualBG) - target_bg) / sens, 2);
if (minDelta < 0 && minDelta > expectedDelta) {
var newinsulinReq = round(( insulinReq * (1 - (minDelta / expectedDelta)) ), 2);
//console.error("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq;
}
// if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-basaliob) {
rT.reason += "max_iob " + max_iob + ", ";
insulinReq = max_iob-basaliob;
}
// rate required to deliver insulinReq more insulin over 30m:
var rate = basal + (2 * insulinReq);
rate = round_basal(rate, profile);
// var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * basal);
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
if (rate > maxSafeBasal) {
rT.reason += "adj. req. rate: "+rate+" to maxSafeBasal: "+maxSafeBasal+", ";
rate = round_basal(maxSafeBasal, profile);
}
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > 2 * req " + insulinReq + ". Setting temp basal of " + rate + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (currenttemp.duration > 5 && (round_basal(rate, profile) <= round_basal(currenttemp.rate, profile))) { // if required temp <~ existing temp basal
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr";
return rT;
}
// required temp > existing temp basal
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
};
module.exports = determine_basal;

View file

@ -0,0 +1,46 @@
var endsWith = function endsWith(text, val) {
return text.indexOf(val, text.length - val.length) !== -1;
}
var round_basal = function round_basal(basal, profile) {
/* x23 and x54 pumps change basal increment depending on how much basal is being delivered:
0.025u for 0.025 < x < 0.975
0.05u for 1 < x < 9.95
0.1u for 10 < x
To round numbers nicely for the pump, use a scale factor of (1 / increment). */
var lowest_rate_scale = 20;
// Has profile even been passed in?
if (typeof profile !== 'undefined')
{
// Make sure optional model has been set
if (typeof profile.model == 'string')
{
if (endsWith(profile.model, "54") || endsWith(profile.model, "23"))
{
lowest_rate_scale = 40;
}
}
}
var rounded_result = basal;
// Shouldn't need to check against 0 as pumps can't deliver negative basal anyway?
if (basal < 1)
{
rounded_basal = Math.round(basal * lowest_rate_scale) / lowest_rate_scale;
}
else if (basal < 10)
{
rounded_basal = Math.round(basal * 20) / 20;
}
else
{
rounded_basal = Math.round(basal * 10) / 10;
}
return rounded_basal;
}
exports = module.exports = round_basal

View file

@ -7,7 +7,7 @@ public class Config {
// MAIN FUCTIONALITY // MAIN FUCTIONALITY
public static final boolean APS = BuildConfig.APS; public static final boolean APS = BuildConfig.APS;
// PLUGINS // PLUGINS
public static final boolean OPENAPSMAENABLED = APS; public static final boolean OPENAPSENABLED = APS;
public static final boolean LOOPENABLED = APS; public static final boolean LOOPENABLED = APS;
public static final boolean WEAR = BuildConfig.WEAR; public static final boolean WEAR = BuildConfig.WEAR;

View file

@ -6,7 +6,7 @@ import com.j256.ormlite.stmt.query.In;
* Created by mike on 07.06.2016. * Created by mike on 07.06.2016.
*/ */
public class Constants { public class Constants {
public static final String MGDL = "mg/dl"; // This is Nightscout representation public static final String MGDL = "mg/dl"; // This is Nightscout's representation
public static final String MMOL = "mmol"; public static final String MMOL = "mmol";
public static final double MMOLL_TO_MGDL = 18; // 18.0182; public static final double MMOLL_TO_MGDL = 18; // 18.0182;
@ -24,8 +24,21 @@ public class Constants {
public static final long keepAliveMsecs = 5 * 60 * 1000L; public static final long keepAliveMsecs = 5 * 60 * 1000L;
// SMS COMMUNICATOR
public static final long remoteBolusMinDistance = 15 * 60 * 1000L; public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
// AMA
public static final int MAX_DAILY_SAFETY_MULTIPLIER = 3;
public static final int CURRENT_BASAL_SAFETY_MULTIPLIER = 4;
public static final int BOLUSSNOOZE_DIA_ADVISOR = 2;
public static final double AUTOSENS_MAX = 1.2d;
public static final double AUTOSENS_MIN = 0.7d;
public static final boolean AUTOSENS_ADJUST_TARGETS = false;
public static final double MIN_5M_CARBIMPACT = 3d;
// Circadian Percentage Profile // Circadian Percentage Profile
public static final int CPP_MIN_PERCENTAGE = 50; public static final int CPP_MIN_PERCENTAGE = 50;
public static final int CPP_MAX_PERCENTAGE = 200; public static final int CPP_MAX_PERCENTAGE = 200;

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.plugins.Loop.LoopFragment;
import info.nightscout.androidaps.plugins.MDI.MDIFragment; import info.nightscout.androidaps.plugins.MDI.MDIFragment;
import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment; import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment; import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAFragment;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment; import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.androidaps.plugins.SafetyFragment.SafetyFragment; import info.nightscout.androidaps.plugins.SafetyFragment.SafetyFragment;
@ -38,6 +39,7 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment;
import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangeFragment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment; import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
import info.nightscout.androidaps.plugins.Wear.WearFragment; import info.nightscout.androidaps.plugins.Wear.WearFragment;
@ -82,11 +84,13 @@ public class MainApp extends Application {
pluginsList.add(MDIFragment.getPlugin()); pluginsList.add(MDIFragment.getPlugin());
pluginsList.add(VirtualPumpFragment.getPlugin()); pluginsList.add(VirtualPumpFragment.getPlugin());
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin()); if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin());
if (Config.OPENAPSMAENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin()); if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSAMAFragment.getPlugin());
pluginsList.add(NSProfileFragment.getPlugin()); pluginsList.add(NSProfileFragment.getPlugin());
pluginsList.add(SimpleProfileFragment.getPlugin()); pluginsList.add(SimpleProfileFragment.getPlugin());
pluginsList.add(LocalProfileFragment.getPlugin()); pluginsList.add(LocalProfileFragment.getPlugin());
pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
pluginsList.add(TempTargetRangeFragment.getPlugin());
pluginsList.add(TreatmentsFragment.getPlugin()); pluginsList.add(TreatmentsFragment.getPlugin());
pluginsList.add(TempBasalsFragment.getPlugin()); pluginsList.add(TempBasalsFragment.getPlugin());
pluginsList.add(SafetyFragment.getPlugin()); pluginsList.add(SafetyFragment.getPlugin());

View file

@ -15,9 +15,9 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.DanaR.BluetoothDevicePreference; import info.nightscout.androidaps.plugins.DanaR.BluetoothDevicePreference;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.utils.LocaleHelper; import info.nightscout.utils.LocaleHelper;
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@ -85,8 +85,10 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(R.xml.pref_treatments); addPreferencesFromResource(R.xml.pref_treatments);
if (Config.APS) if (Config.APS)
addPreferencesFromResource(R.xml.pref_closedmode); addPreferencesFromResource(R.xml.pref_closedmode);
if (Config.OPENAPSMAENABLED) if (Config.OPENAPSENABLED)
addPreferencesFromResource(R.xml.pref_openapsma); addPreferencesFromResource(R.xml.pref_openapsma);
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS))
addPreferencesFromResource(R.xml.pref_openapsama);
addPreferencesFromResource(R.xml.pref_nightscout); addPreferencesFromResource(R.xml.pref_nightscout);
if (Config.DANAR) { if (Config.DANAR) {
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.db.DanaRHistoryRecord;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
@ -39,12 +40,16 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin; import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.Overview.Notification;
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.EventNewNotification;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; 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.plugins.TempTargetRange.events.EventTempTargetRangeChange;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.client.data.NSSgv; import info.nightscout.client.data.NSSgv;
@ -251,10 +256,15 @@ public class DataService extends IntentService {
ConfigBuilderPlugin.nsClientVersionCode = bundles.getInt("nsclientversioncode"); // for ver 1.17 contains 117 ConfigBuilderPlugin.nsClientVersionCode = bundles.getInt("nsclientversioncode"); // for ver 1.17 contains 117
ConfigBuilderPlugin.nsClientVersionName = bundles.getString("nsclientversionname"); ConfigBuilderPlugin.nsClientVersionName = bundles.getString("nsclientversionname");
log.debug("Got versions: NSClient: " + ConfigBuilderPlugin.nsClientVersionName + " Nightscout: " + ConfigBuilderPlugin.nightscoutVersionName); log.debug("Got versions: NSClient: " + ConfigBuilderPlugin.nsClientVersionName + " Nightscout: " + ConfigBuilderPlugin.nightscoutVersionName);
if (ConfigBuilderPlugin.nsClientVersionCode < 118) if (ConfigBuilderPlugin.nsClientVersionCode < 121) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver)); Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
} else {
MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT));
}
} else { } else {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver)); Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
} }
if (bundles.containsKey("status")) { if (bundles.containsKey("status")) {
try { try {
@ -379,6 +389,7 @@ public class DataService extends IntentService {
JSONObject trJson = new JSONObject(trstring); JSONObject trJson = new JSONObject(trstring);
String _id = trJson.getString("_id"); String _id = trJson.getString("_id");
removeTreatmentFromDb(_id); removeTreatmentFromDb(_id);
handleRemoveTempTargetRecord(trJson);
} }
if (bundles.containsKey("treatments")) { if (bundles.containsKey("treatments")) {
@ -388,6 +399,7 @@ public class DataService extends IntentService {
JSONObject trJson = jsonArray.getJSONObject(i); JSONObject trJson = jsonArray.getJSONObject(i);
String _id = trJson.getString("_id"); String _id = trJson.getString("_id");
removeTreatmentFromDb(_id); removeTreatmentFromDb(_id);
handleRemoveTempTargetRecord(trJson);
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -443,6 +455,7 @@ public class DataService extends IntentService {
private void handleAddedTreatment(String trstring) throws JSONException, SQLException { private void handleAddedTreatment(String trstring) throws JSONException, SQLException {
JSONObject trJson = new JSONObject(trstring); JSONObject trJson = new JSONObject(trstring);
handleDanaRHistoryRecords(trJson); // update record _id in history handleDanaRHistoryRecords(trJson); // update record _id in history
handleAddChangeTempTargetRecord(trJson);
if (!trJson.has("insulin") && !trJson.has("carbs")) { if (!trJson.has("insulin") && !trJson.has("carbs")) {
if (Config.logIncommingData) if (Config.logIncommingData)
log.debug("ADD: Uninterested treatment: " + trstring); log.debug("ADD: Uninterested treatment: " + trstring);
@ -480,8 +493,16 @@ public class DataService extends IntentService {
treatment.created_at = new Date(trJson.getLong("mills")); treatment.created_at = new Date(trJson.getLong("mills"));
if (trJson.has("eventType")) { if (trJson.has("eventType")) {
treatment.mealBolus = true; treatment.mealBolus = true;
if (trJson.get("eventType").equals("Correction Bolus")) treatment.mealBolus = false; if (trJson.get("eventType").equals("Correction Bolus"))
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0) treatment.mealBolus = false;
double carbs = treatment.carbs;
if (trJson.has("boluscalc")) {
JSONObject boluscalc = trJson.getJSONObject("boluscalc");
if (boluscalc.has("carbs")) {
carbs = Math.max(boluscalc.getDouble("carbs"), carbs);
}
}
if (carbs <= 0)
treatment.mealBolus = false; treatment.mealBolus = false;
} }
treatment.setTimeIndex(treatment.getTimeIndex()); treatment.setTimeIndex(treatment.getTimeIndex());
@ -499,6 +520,7 @@ public class DataService extends IntentService {
private void handleChangedTreatment(String trstring) throws JSONException, SQLException { private void handleChangedTreatment(String trstring) throws JSONException, SQLException {
JSONObject trJson = new JSONObject(trstring); JSONObject trJson = new JSONObject(trstring);
handleDanaRHistoryRecords(trJson); // update record _id in history handleDanaRHistoryRecords(trJson); // update record _id in history
handleAddChangeTempTargetRecord(trJson);
if (!trJson.has("insulin") && !trJson.has("carbs")) { if (!trJson.has("insulin") && !trJson.has("carbs")) {
if (Config.logIncommingData) if (Config.logIncommingData)
log.debug("CHANGE: Uninterested treatment: " + trstring); log.debug("CHANGE: Uninterested treatment: " + trstring);
@ -532,8 +554,16 @@ public class DataService extends IntentService {
treatment.created_at = new Date(trJson.getLong("mills")); treatment.created_at = new Date(trJson.getLong("mills"));
if (trJson.has("eventType")) { if (trJson.has("eventType")) {
treatment.mealBolus = true; treatment.mealBolus = true;
if (trJson.get("eventType").equals("Correction Bolus")) treatment.mealBolus = false; if (trJson.get("eventType").equals("Correction Bolus"))
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0) treatment.mealBolus = false;
double carbs = treatment.carbs;
if (trJson.has("boluscalc")) {
JSONObject boluscalc = trJson.getJSONObject("boluscalc");
if (boluscalc.has("carbs")) {
carbs = Math.max(boluscalc.getDouble("carbs"), carbs);
}
}
if (carbs <= 0)
treatment.mealBolus = false; treatment.mealBolus = false;
} }
treatment.setTimeIndex(treatment.getTimeIndex()); treatment.setTimeIndex(treatment.getTimeIndex());
@ -573,6 +603,86 @@ public class DataService extends IntentService {
} }
} }
/*
{
"_id": "58795998aa86647ba4d68ce7",
"enteredBy": "",
"eventType": "Temporary Target",
"reason": "Eating Soon",
"targetTop": 80,
"targetBottom": 80,
"duration": 120,
"created_at": "2017-01-13T22:50:00.782Z",
"carbs": null,
"insulin": null
}
*/
public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException, SQLException {
if (trJson.has("eventType") && trJson.getString("eventType").equals("Temporary Target")) {
if (Config.logIncommingData)
log.debug("Processing TempTarget record: " + trJson.toString());
Dao<TempTarget, Long> daoTempTargets = MainApp.getDbHelper().getDaoTempTargets();
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", trJson.getString("_id")).or().eq("timeIndex", trJson.getLong("mills"));
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
List<TempTarget> list = daoTempTargets.query(preparedQuery);
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return; // no profile data, better ignore than do something wrong
String units = profile.getUnits();
if (list.size() == 0) {
// Record does not exists. add
TempTarget newRecord = new TempTarget();
newRecord.timeStart = new Date(trJson.getLong("mills"));
newRecord.duration = trJson.getInt("duration");
newRecord.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units);
newRecord.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units);
newRecord.reason = trJson.getString("reason");
newRecord._id = trJson.getString("_id");
newRecord.setTimeIndex(newRecord.getTimeIndex());
daoTempTargets.createIfNotExists(newRecord);
if (Config.logIncommingData)
log.debug("Adding TempTarget record to database: " + newRecord.log());
MainApp.bus().post(new EventTempTargetRangeChange());
} else if (list.size() == 1) {
if (Config.logIncommingData)
log.debug("Updating TempTarget record in database: " + trJson.getString("_id"));
TempTarget record = list.get(0);
record.timeStart = new Date(trJson.getLong("mills"));
record.duration = trJson.getInt("duration");
record.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units);
record.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units);
record.reason = trJson.getString("reason");
record._id = trJson.getString("_id");
daoTempTargets.update(record);
MainApp.bus().post(new EventTempTargetRangeChange());
}
}
}
public void handleRemoveTempTargetRecord(JSONObject trJson) throws JSONException, SQLException {
if (trJson.has("_id")) {
Dao<TempTarget, Long> daoTempTargets = MainApp.getDbHelper().getDaoTempTargets();
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", trJson.getString("_id"));
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
List<TempTarget> list = daoTempTargets.query(preparedQuery);
if (list.size() == 1) {
TempTarget record = list.get(0);
if (Config.logIncommingData)
log.debug("Removing TempTarget record from database: " + record.log());
daoTempTargets.delete(record);
MainApp.bus().post(new EventTempTargetRangeChange());
} else {
if (Config.logIncommingData)
log.debug("TempTarget not found database: " + trJson.toString());
}
}
}
@Nullable @Nullable
public static Treatment findById(String _id) { public static Treatment findById(String _id) {
try { try {

View file

@ -0,0 +1,126 @@
package info.nightscout.androidaps.data;
import android.support.annotation.Nullable;
import android.text.Html;
import android.text.Spanned;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
/**
* Created by mike on 04.01.2017.
*/
public class GlucoseStatus {
public double glucose = 0d;
public double delta = 0d;
public double avgdelta = 0d;
public double short_avgdelta = 0d;
public double long_avgdelta = 0d;
@Override
public String toString() {
return MainApp.sResources.getString(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
MainApp.sResources.getString(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
MainApp.sResources.getString(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" +
MainApp.sResources.getString(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl";
}
public Spanned toSpanned() {
return Html.fromHtml("<b>" + MainApp.sResources.getString(R.string.glucose) + "</b>: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl<br>" +
"<b>" + MainApp.sResources.getString(R.string.delta) + "</b>: " + DecimalFormatter.to0Decimal(delta) + " mg/dl<br>" +
"<b>" + MainApp.sResources.getString(R.string.short_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl<br>" +
"<b>" + MainApp.sResources.getString(R.string.long_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl");
}
public GlucoseStatus() {
}
public GlucoseStatus round() {
this.glucose = Round.roundTo(this.glucose, 0.1);
this.delta = Round.roundTo(this.delta, 0.01);
this.avgdelta = Round.roundTo(this.avgdelta, 0.01);
this.short_avgdelta = Round.roundTo(this.short_avgdelta, 0.01);
this.long_avgdelta = Round.roundTo(this.long_avgdelta, 0.01);
return this;
}
@Nullable
public static GlucoseStatus getGlucoseStatusData() {
// load 45min
long fromtime = (long) (new Date().getTime() - 60 * 1000L * 45);
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
int sizeRecords = data.size();
if (sizeRecords < 4 || data.get(0).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
return null;
}
BgReading now = data.get(0);
long now_date = now.timeIndex;
double change;
ArrayList<Double> last_deltas = new ArrayList<Double>();
ArrayList<Double> short_deltas = new ArrayList<Double>();
ArrayList<Double> long_deltas = new ArrayList<Double>();
for (int i = 1; i < data.size(); i++) {
if (data.get(i).value > 38) {
BgReading then = data.get(i);
long then_date = then.timeIndex;
double avgdelta = 0;
int minutesago;
minutesago = Math.round((now_date - then_date) / (1000 * 60));
// multiply by 5 to get the same units as delta, i.e. mg/dL/5m
change = now.value - then.value;
avgdelta = change / minutesago * 5;
// use the average of all data points in the last 2.5m for all further "now" calculations
if (0 < minutesago && minutesago < 2.5) {
now.value = (now.value + then.value) / 2;
now_date = (now_date + then_date) / 2;
// short_deltas are calculated from everything ~5-15 minutes ago
} else if (2.5 < minutesago && minutesago < 17.5) {
//console.error(minutesago, avgdelta);
short_deltas.add(avgdelta);
// last_deltas are calculated from everything ~5 minutes ago
if (2.5 < minutesago && minutesago < 7.5) {
last_deltas.add(avgdelta);
}
// long_deltas are calculated from everything ~20-40 minutes ago
} else if (17.5 < minutesago && minutesago < 42.5) {
long_deltas.add(avgdelta);
}
}
}
GlucoseStatus status = new GlucoseStatus();
status.glucose = now.value;
status.delta = average(last_deltas);
status.short_avgdelta = average(short_deltas);
status.long_avgdelta = average(long_deltas);
status.avgdelta = status.short_avgdelta; // for OpenAPS MA
return status.round();
}
public static double average(ArrayList<Double> array) {
double sum = 0d;
if (array.size() == 0)
return 0d;
for (Double value : array) {
sum += value;
}
return sum / array.size();
}
}

View file

@ -0,0 +1,137 @@
package info.nightscout.androidaps.data;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
public class IobTotal {
public Double iob;
public Double activity;
public Double bolussnooze;
public Double basaliob;
public Double netbasalinsulin;
public Double hightempinsulin;
public Double netInsulin = 0d; // for calculations from temp basals only
public Double netRatio = 0d; // for calculations from temp basals only
long time;
public IobTotal(long time) {
this.iob = 0d;
this.activity = 0d;
this.bolussnooze = 0d;
this.basaliob = 0d;
this.netbasalinsulin = 0d;
this.hightempinsulin = 0d;
this.time = time;
}
public IobTotal plus(IobTotal other) {
iob += other.iob;
activity += other.activity;
bolussnooze += other.bolussnooze;
basaliob += other.basaliob;
netbasalinsulin += other.netbasalinsulin;
hightempinsulin += other.hightempinsulin;
netInsulin += other.netInsulin;
netRatio += other.netRatio;
return this;
}
public static IobTotal combine(IobTotal bolusIOB, IobTotal basalIob) {
IobTotal result = new IobTotal(bolusIOB.time);
result.iob = bolusIOB.iob + basalIob.basaliob;
result.activity = bolusIOB.activity + basalIob.activity;
result.bolussnooze = bolusIOB.bolussnooze;
result.basaliob = basalIob.basaliob;
result.netbasalinsulin = basalIob.netbasalinsulin;
result.hightempinsulin = basalIob.hightempinsulin;
return result;
}
public IobTotal round() {
this.iob = Round.roundTo(this.iob, 0.001);
this.activity = Round.roundTo(this.activity, 0.0001);
this.bolussnooze = Round.roundTo(this.bolussnooze, 0.0001);
this.basaliob = Round.roundTo(this.basaliob, 0.001);
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
return this;
}
public JSONObject json() {
JSONObject json = new JSONObject();
try {
json.put("iob", iob);
json.put("basaliob", basaliob);
json.put("activity", activity);
json.put("time", DateUtil.toISOString(new Date()));
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
public JSONObject determineBasalJson() {
JSONObject json = new JSONObject();
try {
json.put("iob", iob);
json.put("basaliob", basaliob);
json.put("bolussnooze", bolussnooze);
json.put("activity", activity);
json.put("time", DateUtil.toISOString(new Date(time)));
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
public static IobTotal calulateFromTreatmentsAndTemps() {
ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round();
ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round();
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
return iobTotal;
}
public static IobTotal calulateFromTreatmentsAndTemps(long time) {
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round();
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round();
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
return iobTotal;
}
public static IobTotal[] calculateIobArrayInDia() {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
// predict IOB out to DIA plus 30m
long time = new Date().getTime();
int len = (int) ((profile.getDia() *60 + 30) / 5);
IobTotal[] array = new IobTotal[len];
int pos = 0;
for (int i = 0; i < len; i++){
long t = time + i * 5 * 60000;
IobTotal iob = calulateFromTreatmentsAndTemps(t);
array[pos] = iob;
pos++;
}
return array;
}
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
JSONArray array = new JSONArray();
for (int i = 0; i < iobArray.length; i ++) {
array.put(iobArray[i].determineBasalJson());
}
return array;
}
}

View file

@ -0,0 +1,45 @@
package info.nightscout.androidaps.data;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens;
import info.nightscout.androidaps.plugins.OpenAPSAMA.AutosensResult;
import info.nightscout.client.data.NSProfile;
/**
* Created by mike on 04.01.2017.
*/
public class MealData {
public double boluses = 0d;
public double carbs = 0d;
public double mealCOB = 0.0d; // TODO: add calculation for AMA
public void addTreatment(Treatment treatment) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return;
// TODO: not sure how much data do i need for AMA
List<BgReading> bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * profile.getDia() * 2), false);
long now = new Date().getTime();
long dia_ago = now - (new Double(profile.getDia() * 60 * 60 * 1000l)).longValue();
long t = treatment.created_at.getTime();
if (t > dia_ago && t <= now) {
if (treatment.carbs >= 1) {
carbs += treatment.carbs;
AutosensResult result = Autosens.detectSensitivityandCarbAbsorption(bgReadings, t);
double myCarbsAbsorbed = result.carbsAbsorbed;
double myMealCOB = Math.max(0, carbs - myCarbsAbsorbed);
mealCOB = Math.max(mealCOB, myMealCOB);
}
if (treatment.insulin > 0 && treatment.mealBolus) {
boluses += treatment.insulin;
}
}
}
}

View file

@ -14,7 +14,7 @@ import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
public class PumpEnactResult extends Object implements Parcelable { public class PumpEnactResult extends Object {
public boolean success = false; // request was processed successfully (but possible no change was needed) public boolean success = false; // request was processed successfully (but possible no change was needed)
public boolean enacted = false; // request was processed successfully and change has been made public boolean enacted = false; // request was processed successfully and change has been made
public String comment = ""; public String comment = "";
@ -85,43 +85,6 @@ public class PumpEnactResult extends Object implements Parcelable {
return Html.fromHtml(ret); return Html.fromHtml(ret);
} }
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(success ? 1 : 0);
dest.writeInt(enacted ? 1 : 0);
dest.writeInt(isPercent ? 1 : 0);
dest.writeString(comment);
dest.writeInt(duration);
dest.writeDouble(absolute);
dest.writeInt(percent);
}
public final Parcelable.Creator<PumpEnactResult> CREATOR = new Parcelable.Creator<PumpEnactResult>() {
public PumpEnactResult createFromParcel(Parcel in) {
return new PumpEnactResult(in);
}
public PumpEnactResult[] newArray(int size) {
return new PumpEnactResult[size];
}
};
protected PumpEnactResult(Parcel in) {
success = in.readInt() == 1 ? true : false;
enacted = in.readInt() == 1 ? true : false;
isPercent = in.readInt() == 1 ? true : false;
duration = in.readInt();
comment = in.readString();
absolute = in.readDouble();
percent = in.readInt();
}
public PumpEnactResult() { public PumpEnactResult() {
} }

View file

@ -3,11 +3,7 @@ package info.nightscout.androidaps.db;
import android.content.Context; import android.content.Context;
import android.database.DatabaseUtils; import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.Html;
import android.text.Spanned;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.Dao;
@ -27,9 +23,7 @@ import java.util.List;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class); private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
@ -37,6 +31,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_NAME = "AndroidAPSDb"; public static final String DATABASE_NAME = "AndroidAPSDb";
public static final String DATABASE_BGREADINGS = "BgReadings"; public static final String DATABASE_BGREADINGS = "BgReadings";
public static final String DATABASE_TEMPBASALS = "TempBasals"; public static final String DATABASE_TEMPBASALS = "TempBasals";
public static final String DATABASE_TEMPTARGETS = "TempTargets";
public static final String DATABASE_TREATMENTS = "Treatments"; public static final String DATABASE_TREATMENTS = "Treatments";
public static final String DATABASE_DANARHISTORY = "DanaRHistory"; public static final String DATABASE_DANARHISTORY = "DanaRHistory";
@ -44,6 +39,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public DatabaseHelper(Context context) { public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
onCreate(getWritableDatabase(), getConnectionSource());
} }
@ -52,11 +48,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try { try {
log.info("onCreate"); log.info("onCreate");
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class); TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
} catch (SQLException e) { } catch (SQLException e) {
log.error(DatabaseHelper.class.getName(), "Can't create database", e); log.error("Can't create database", e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@ -66,12 +63,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try { try {
log.info(DatabaseHelper.class.getName(), "onUpgrade"); log.info(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TempBasal.class, true); TableUtils.dropTable(connectionSource, TempBasal.class, true);
TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
onCreate(database, connectionSource); onCreate(database, connectionSource);
} catch (SQLException e) { } catch (SQLException e) {
log.error(DatabaseHelper.class.getName(), "Can't drop databases", e); log.error("Can't drop databases", e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@ -87,35 +85,38 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void cleanUpDatabases() { public void cleanUpDatabases() {
// TODO: call it somewhere // TODO: call it somewhere
log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
getWritableDatabase().delete("BgReadings", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); getWritableDatabase().delete(DATABASE_BGREADINGS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
log.debug("Before TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS)); log.debug("Before TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS));
getWritableDatabase().delete("TempBasals", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); getWritableDatabase().delete(DATABASE_TEMPBASALS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS)); log.debug("After TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS));
log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
getWritableDatabase().delete(DATABASE_TEMPTARGETS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
getWritableDatabase().delete("Treatments", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); getWritableDatabase().delete(DATABASE_TREATMENTS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "DanaRHistory")); log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
getWritableDatabase().delete("History", "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "DanaRHistory")); log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
} }
public void resetDatabases() { public void resetDatabases() {
try { try {
TableUtils.dropTable(connectionSource, TempBasal.class, true); TableUtils.dropTable(connectionSource, TempBasal.class, true);
TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class); TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
// MainApp.bus().post(new EventNewBG());
// MainApp.bus().post(new EventTreatmentChange());
// MainApp.bus().post(new EventTempBasalChange());
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -123,7 +124,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void resetTreatments() { public void resetTreatments() {
try { try {
TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
} catch (SQLException e) { } catch (SQLException e) {
@ -131,10 +131,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
} }
public void resetTempTargets() {
try {
TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
public Dao<TempBasal, Long> getDaoTempBasals() throws SQLException { public Dao<TempBasal, Long> getDaoTempBasals() throws SQLException {
return getDao(TempBasal.class); return getDao(TempBasal.class);
} }
public Dao<TempTarget, Long> getDaoTempTargets() throws SQLException {
return getDao(TempTarget.class);
}
public Dao<Treatment, Long> getDaoTreatments() throws SQLException { public Dao<Treatment, Long> getDaoTreatments() throws SQLException {
return getDao(Treatment.class); return getDao(Treatment.class);
} }
@ -189,12 +202,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null; return null;
} }
public List<BgReading> getDataFromTime(long mills) { public List<BgReading> getBgreadingsDataFromTime(long mills, boolean ascending) {
try { try {
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings(); Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
List<BgReading> bgReadings; List<BgReading> bgReadings;
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder(); QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
queryBuilder.orderBy("timeIndex", true); queryBuilder.orderBy("timeIndex", ascending);
Where where = queryBuilder.where(); Where where = queryBuilder.where();
where.ge("timeIndex", mills).and().gt("value", 38); where.ge("timeIndex", mills).and().gt("value", 38);
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare(); PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
@ -206,126 +219,56 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<BgReading>(); return new ArrayList<BgReading>();
} }
/* public List<Treatment> getTreatmentDataFromTime(long mills, boolean ascending) {
* Returns glucose_status for openAPS or null if no actual data available
*/
public static class GlucoseStatus implements Parcelable {
public double glucose = 0d;
public double delta = 0d;
public double avgdelta = 0d;
@Override
public String toString() {
return MainApp.sResources.getString(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
MainApp.sResources.getString(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
MainApp.sResources.getString(R.string.avgdelta) + " " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl";
}
public Spanned toSpanned() {
return Html.fromHtml("<b>" + MainApp.sResources.getString(R.string.glucose) + "</b>: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl<br>" +
"<b>" + MainApp.sResources.getString(R.string.delta) + "</b>: " + DecimalFormatter.to0Decimal(delta) + " mg/dl<br>" +
"<b>" + MainApp.sResources.getString(R.string.avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl");
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeDouble(avgdelta);
dest.writeDouble(delta);
dest.writeDouble(glucose);
}
public final Parcelable.Creator<GlucoseStatus> CREATOR = new Parcelable.Creator<GlucoseStatus>() {
public GlucoseStatus createFromParcel(Parcel in) {
return new GlucoseStatus(in);
}
public GlucoseStatus[] newArray(int size) {
return new GlucoseStatus[size];
}
};
private GlucoseStatus(Parcel in) {
avgdelta = in.readDouble();
delta = in.readDouble();
glucose = in.readDouble();
}
public GlucoseStatus() {
}
public GlucoseStatus(Double glucose, Double delta, Double avgdelta) {
this.glucose = glucose;
this.delta = delta;
this.avgdelta = avgdelta;
}
public GlucoseStatus round() {
this.glucose = Round.roundTo(this.glucose, 0.1);
this.delta = Round.roundTo(this.delta, 0.01);
this.avgdelta = Round.roundTo(this.avgdelta, 0.01);
return this;
}
}
@Nullable
public GlucoseStatus getGlucoseStatusData() {
GlucoseStatus result = new GlucoseStatus();
try { try {
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
Dao<BgReading, Long> daoBgreadings = null; List<Treatment> treatments;
daoBgreadings = getDaoBgReadings(); QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
List<BgReading> bgReadings; queryBuilder.orderBy("timeIndex", ascending);
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder(); Where where = queryBuilder.where();
queryBuilder.orderBy("timeIndex", false); where.ge("timeIndex", mills);
queryBuilder.where().gt("value", 38); PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
queryBuilder.limit(4l); treatments = daoTreatments.query(preparedQuery);
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare(); return treatments;
bgReadings = daoBgreadings.query(preparedQuery);
int sizeRecords = bgReadings.size();
if (sizeRecords < 4 || bgReadings.get(sizeRecords - 4).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
return null;
}
double minutes = 5;
double change;
double avg;
if (bgReadings.size() > 3) {
BgReading now = bgReadings.get(sizeRecords - 4);
BgReading last = bgReadings.get(sizeRecords - 3);
BgReading last1 = bgReadings.get(sizeRecords - 2);
BgReading last2 = bgReadings.get(sizeRecords - 1);
if (last2.value > 38) {
minutes = (now.timeIndex - last2.timeIndex)/(60d*1000);
change = now.value - last2.value;
} else if (last1.value > 38) {
minutes = (now.timeIndex - last1.timeIndex)/(60d*1000);;
change = now.value - last1.value;
} else if (last.value > 38) {
minutes = (now.timeIndex - last.timeIndex)/(60d*1000);
change = now.value - last.value;
} else {
change = 0;
}
//multiply by 5 to get the same unit as delta, i.e. mg/dL/5m
avg = change / minutes * 5;
result.glucose = now.value;
result.delta = (now.value - last.value)*5*60*1000/(now.getTimeIndex() - last.getTimeIndex());
result.avgdelta = avg;
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
return null;
} }
result.round(); return new ArrayList<Treatment>();
return result;
} }
public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) {
try {
Dao<TempTarget, Long> daoTempTargets = getDaoTempTargets();
List<TempTarget> tempTargets;
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
queryBuilder.orderBy("timeIndex", ascending);
Where where = queryBuilder.where();
where.ge("timeIndex", mills);
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
tempTargets = daoTempTargets.query(preparedQuery);
return tempTargets;
} catch (SQLException e) {
e.printStackTrace();
}
return new ArrayList<TempTarget>();
}
public List<TempBasal> getTempbasalsDataFromTime(long mills, boolean ascending, boolean isExtended) {
try {
Dao<TempBasal, Long> daoTempbasals = getDaoTempBasals();
List<TempBasal> tempbasals;
QueryBuilder<TempBasal, Long> queryBuilder = daoTempbasals.queryBuilder();
queryBuilder.orderBy("timeIndex", ascending);
Where where = queryBuilder.where();
where.ge("timeIndex", mills).and().eq("isExtended", isExtended);
PreparedQuery<TempBasal> preparedQuery = queryBuilder.prepare();
tempbasals = daoTempbasals.query(preparedQuery);
return tempbasals;
} catch (SQLException e) {
e.printStackTrace();
}
return new ArrayList<TempBasal>();
}
} }

View file

@ -10,7 +10,7 @@ import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
@ -53,7 +53,7 @@ public class TempBasal {
public IobTotal iobCalc(Date time) { public IobTotal iobCalc(Date time) {
IobTotal result = new IobTotal(); IobTotal result = new IobTotal(time.getTime());
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) if (profile == null)

View file

@ -0,0 +1,78 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.utils.DecimalFormatter;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS)
public class TempTarget {
private static Logger log = LoggerFactory.getLogger(TempTarget.class);
public long getTimeIndex() {
return timeStart.getTime() - timeStart.getTime() % 1000;
}
public void setTimeIndex(long timeIndex) {
this.timeIndex = timeIndex;
}
@DatabaseField(id = true, useGetSet = true)
public long timeIndex;
@DatabaseField
public Date timeStart;
@DatabaseField
public double low; // in mgdl
@DatabaseField
public double high; // in mgdl
@DatabaseField
public String reason;
@DatabaseField
public int duration; // in minutes
@DatabaseField
public String _id; // NS _id
public Date getPlannedTimeEnd() {
return new Date(timeStart.getTime() + 60 * 1_000 * duration);
}
public String lowValueToUnitsToString(String units) {
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(low);
else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL);
}
public String highValueToUnitsToString(String units) {
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(high);
else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL);
}
public boolean isInProgress() {
return ((TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class)).getTempTargetInProgress(new Date().getTime()) == this;
}
public String log() {
return "TempTarget{" +
"timeIndex=" + timeIndex +
", timeStart=" + timeStart +
", duration=" + duration +
", reason=" + reason +
", low=" + low +
", high=" + high +
'}';
}
}

View file

@ -11,5 +11,5 @@ public interface APSInterface {
public APSResult getLastAPSResult(); public APSResult getLastAPSResult();
public Date getLastAPSRun(); public Date getLastAPSRun();
public void invoke(); public void invoke(String initiator);
} }

View file

@ -3,7 +3,7 @@ package info.nightscout.androidaps.interfaces;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
/** /**
* Created by mike on 14.06.2016. * Created by mike on 14.06.2016.
@ -11,7 +11,10 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
public interface TempBasalsInterface { public interface TempBasalsInterface {
void updateTotalIOB(); void updateTotalIOB();
IobTotal getLastCalculation(); IobTotal getLastCalculation();
IobTotal getCalculationToTime(long time);
TempBasal getTempBasal (Date time); TempBasal getTempBasal (Date time);
TempBasal getExtendedBolus (Date time); TempBasal getExtendedBolus (Date time);
long oldestDataAvaialable();
} }

View file

@ -2,10 +2,9 @@ package info.nightscout.androidaps.interfaces;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
/** /**
* Created by mike on 14.06.2016. * Created by mike on 14.06.2016.
@ -14,6 +13,7 @@ public interface TreatmentsInterface {
void updateTotalIOB(); void updateTotalIOB();
IobTotal getLastCalculation(); IobTotal getLastCalculation();
TreatmentsPlugin.MealData getMealData(); IobTotal getCalculationToTime(long time);
MealData getMealData();
List<Treatment> getTreatments(); List<Treatment> getTreatments();
} }

View file

@ -12,6 +12,7 @@ import android.widget.Button;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
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.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
@ -35,6 +36,7 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
} }
Button profileSwitch; Button profileSwitch;
Button tempTarget;
Button extendedBolus; Button extendedBolus;
Button tempBasal; Button tempBasal;
Button fill; Button fill;
@ -49,11 +51,13 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
View view = inflater.inflate(R.layout.actions_fragment, container, false); View view = inflater.inflate(R.layout.actions_fragment, container, false);
profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch); profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch);
tempTarget = (Button) view.findViewById(R.id.actions_temptarget);
extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus); extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus);
tempBasal = (Button) view.findViewById(R.id.actions_settempbasal); tempBasal = (Button) view.findViewById(R.id.actions_settempbasal);
fill = (Button) view.findViewById(R.id.actions_fill); fill = (Button) view.findViewById(R.id.actions_fill);
profileSwitch.setOnClickListener(this); profileSwitch.setOnClickListener(this);
tempTarget.setOnClickListener(this);
extendedBolus.setOnClickListener(this); extendedBolus.setOnClickListener(this);
tempBasal.setOnClickListener(this); tempBasal.setOnClickListener(this);
fill.setOnClickListener(this); fill.setOnClickListener(this);
@ -106,6 +110,10 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
fill.setVisibility(View.GONE); fill.setVisibility(View.GONE);
else else
fill.setVisibility(View.VISIBLE); fill.setVisibility(View.VISIBLE);
if (!Config.APS)
tempTarget.setVisibility(View.GONE);
else
tempTarget.setVisibility(View.VISIBLE);
} }
}); });
} }
@ -117,11 +125,18 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
switch (view.getId()) { switch (view.getId()) {
case R.id.actions_profileswitch: case R.id.actions_profileswitch:
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
profileswitch.executeProfileSwitch = true; profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch); newDialog.setOptions(profileswitch);
newDialog.show(manager, "NewNSTreatmentDialog"); newDialog.show(manager, "NewNSTreatmentDialog");
break; break;
case R.id.actions_temptarget:
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temptarget, R.string.careportal_temptarget, false, false, false, false, true, false, false, false, false, true);
temptarget.executeTempTarget = true;
newTTDialog.setOptions(temptarget);
newTTDialog.show(manager, "NewNSTreatmentDialog");
break;
case R.id.actions_extendedbolus: case R.id.actions_extendedbolus:
NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog(); NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog();
newExtendedDialog.show(manager, "NewExtendedDialog"); newExtendedDialog.show(manager, "NewExtendedDialog");

View file

@ -25,25 +25,26 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O
return careportalPlugin; return careportalPlugin;
} }
// bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split // bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget
final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false); final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false, false);
final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false); final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false, false);
final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false); final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false, false);
final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false); final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false, false);
final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false); final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false, false);
final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true); final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true, false);
final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false); final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false, false);
final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false); final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false, false);
final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false); final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false, false);
final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false); final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false, false);
final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false); final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false, false);
final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false); final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false);
final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false); final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false);
final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false); final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false);
final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false); final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false);
final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false); final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false);
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false); final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false);
final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temptarget, R.string.careportal_temptarget, false, false, false, false, true, false, false, false, false, true);
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -68,6 +69,7 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O
view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this); view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this);
view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this); view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this);
view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this); view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this);
view.findViewById(R.id.careportal_temptarget).setOnClickListener(this);
return view; return view;
} }
@ -130,6 +132,9 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O
case R.id.careportal_openapsoffline: case R.id.careportal_openapsoffline:
newDialog.setOptions(openapsoffline); newDialog.setOptions(openapsoffline);
break; break;
case R.id.careportal_temptarget:
newDialog.setOptions(temptarget);
break;
default: default:
newDialog = null; newDialog = null;
} }

View file

@ -24,6 +24,7 @@ import android.widget.RadioButton;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import com.j256.ormlite.dao.Dao;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
@ -33,6 +34,7 @@ import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -42,10 +44,13 @@ import java.util.Date;
import info.nightscout.androidaps.Constants; 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.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.PlusMinusEditText; import info.nightscout.utils.PlusMinusEditText;
@ -73,6 +78,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
LinearLayout layoutAbsolute; LinearLayout layoutAbsolute;
LinearLayout layoutCarbTime; LinearLayout layoutCarbTime;
LinearLayout layoutProfile; LinearLayout layoutProfile;
LinearLayout layoutTempTarget;
Button dateButton; Button dateButton;
Button timeButton; Button timeButton;
Button okButton; Button okButton;
@ -91,6 +97,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
EditText carbTimeEdit; EditText carbTimeEdit;
EditText splitEdit; EditText splitEdit;
Spinner profileSpinner; Spinner profileSpinner;
EditText low;
EditText high;
Spinner reasonSpinner;
PlusMinusEditText editBg; PlusMinusEditText editBg;
PlusMinusEditText editCarbs; PlusMinusEditText editCarbs;
@ -142,6 +151,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout); layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout);
layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout); layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout);
layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout); layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout);
layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout);
bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits); bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits);
meterRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_meter); meterRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_meter);
@ -193,6 +203,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes); notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes);
splitEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_splitinput); splitEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_splitinput);
reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason);
low = (EditText) view.findViewById(R.id.careportal_temptarget_low);
high = (EditText) view.findViewById(R.id.careportal_temptarget_high);
eventTime = new Date(); eventTime = new Date();
dateButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventdate); dateButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventdate);
timeButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventtime); timeButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventtime);
@ -204,7 +218,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
okButton = (Button) view.findViewById(R.id.careportal_newnstreatment_ok); okButton = (Button) view.findViewById(R.id.careportal_newnstreatment_ok);
okButton.setOnClickListener(this); okButton.setOnClickListener(this);
// BG // profile
profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
ArrayList<CharSequence> profileList; ArrayList<CharSequence> profileList;
units = Constants.MGDL; units = Constants.MGDL;
@ -227,6 +241,17 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
} }
} }
// temp target
ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>();
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon));
reasonList.add(MainApp.sResources.getString(R.string.activity));
reasonList.add(MainApp.sResources.getString(R.string.manual));
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(),
android.R.layout.simple_spinner_item, reasonList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reasonSpinner.setAdapter(adapterReason);
// bg
bgUnitsView.setText(units); bgUnitsView.setText(units);
// Set BG if not old // Set BG if not old
@ -271,6 +296,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
showOrHide(layoutAbsolute, options.absolute); showOrHide(layoutAbsolute, options.absolute);
showOrHide(layoutCarbTime, options.prebolus); showOrHide(layoutCarbTime, options.prebolus);
showOrHide(layoutProfile, options.profile); showOrHide(layoutProfile, options.profile);
showOrHide(layoutTempTarget, options.tempTarget);
return view; return view;
} }
@ -403,6 +429,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
case R.id.careportal_openapsoffline: case R.id.careportal_openapsoffline:
data.put("eventType", "OpenAPS Offline"); data.put("eventType", "OpenAPS Offline");
break; break;
case R.id.careportal_temptarget:
data.put("eventType", "Temporary Target");
break;
} }
if (SafeParse.stringToDouble(bgInputEdit.getText().toString()) != 0d) { if (SafeParse.stringToDouble(bgInputEdit.getText().toString()) != 0d) {
data.put("glucose", SafeParse.stringToDouble(bgInputEdit.getText().toString())); data.put("glucose", SafeParse.stringToDouble(bgInputEdit.getText().toString()));
@ -426,6 +455,12 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
data.put("preBolus", SafeParse.stringToDouble(carbTimeEdit.getText().toString())); data.put("preBolus", SafeParse.stringToDouble(carbTimeEdit.getText().toString()));
if (!notesEdit.getText().toString().equals("")) if (!notesEdit.getText().toString().equals(""))
data.put("notes", notesEdit.getText().toString()); data.put("notes", notesEdit.getText().toString());
if (!reasonSpinner.getSelectedItem().toString().equals(""))
data.put("reason", reasonSpinner.getSelectedItem().toString());
if (SafeParse.stringToDouble(low.getText().toString()) != 0d)
data.put("targetBottom", SafeParse.stringToDouble(low.getText().toString()));
if (SafeParse.stringToDouble(high.getText().toString()) != 0d)
data.put("targetTop", SafeParse.stringToDouble(high.getText().toString()));
data.put("units", units); data.put("units", units);
if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); if (!enteredBy.equals("")) data.put("enteredBy", enteredBy);
if (options.eventType == R.id.careportal_combobolus) { if (options.eventType == R.id.careportal_combobolus) {
@ -509,6 +544,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
ret += data.get("profile"); ret += data.get("profile");
ret += "\n"; ret += "\n";
} }
if (data.has("targetBottom") && data.has("targetTop")) {
ret += getString(R.string.target_range);
ret += " ";
ret += data.get("targetBottom");
ret += " - ";
ret += data.get("targetTop");
ret += "\n";
}
if (data.has("created_at")) { if (data.has("created_at")) {
ret += getString(R.string.careportal_newnstreatment_eventtime_label); ret += getString(R.string.careportal_newnstreatment_eventtime_label);
ret += ": "; ret += ": ";
@ -563,6 +606,35 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
} else { } else {
ConfigBuilderPlugin.uploadCareportalEntryToNS(data); ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
} }
if (options.executeTempTarget) {
if (data.has("targetBottom") && data.has("targetTop")) {
sHandler.post(new Runnable() {
@Override
public void run() {
try {
TempTarget tempTarget = new TempTarget();
tempTarget.timeStart = eventTime;
tempTarget.duration = data.getInt("duration");
tempTarget.reason = data.getString("reason");
tempTarget.low = NSProfile.toMgdl(data.getDouble("targetBottom"), MainApp.getConfigBuilder().getActiveProfile().getProfile().getUnits());
tempTarget.high = NSProfile.toMgdl(data.getDouble("targetTop"), MainApp.getConfigBuilder().getActiveProfile().getProfile().getUnits());
tempTarget.setTimeIndex(tempTarget.getTimeIndex());
Dao<TempTarget, Long> dao = MainApp.getDbHelper().getDaoTempTargets();
log.debug("Creating new TempTarget db record: " + tempTarget.log());
dao.createIfNotExists(tempTarget);
MainApp.bus().post(new EventTempTargetRangeChange());
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
} catch (JSONException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
} else {
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
}
} }
}); });
builder.setNegativeButton(getContext().getString(R.string.cancel), null); builder.setNegativeButton(getContext().getString(R.string.cancel), null);

View file

@ -16,9 +16,11 @@ public class OptionsToShow {
public boolean absolute; public boolean absolute;
public boolean profile; public boolean profile;
public boolean split; public boolean split;
public boolean tempTarget;
// perform direct actions // perform direct actions
public boolean executeProfileSwitch = false; public boolean executeProfileSwitch = false;
public boolean executeTempTarget = false;
public OptionsToShow(int eventType, public OptionsToShow(int eventType,
int eventName, int eventName,
@ -30,7 +32,8 @@ public class OptionsToShow {
boolean percent, boolean percent,
boolean absolute, boolean absolute,
boolean profile, boolean profile,
boolean split) { boolean split,
boolean tempTarget) {
this.eventType = eventType; this.eventType = eventType;
this.eventName = eventName; this.eventName = eventName;
this.bg = bg; this.bg = bg;
@ -42,5 +45,6 @@ public class OptionsToShow {
this.absolute = absolute; this.absolute = absolute;
this.profile = profile; this.profile = profile;
this.split = split; this.split = split;
this.tempTarget = tempTarget;
} }
} }

View file

@ -133,7 +133,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
@Override @Override
public void onClick(View view) { public void onClick(View view) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
profileswitch.executeProfileSwitch = true; profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch); newDialog.setOptions(profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");

View file

@ -43,13 +43,13 @@ import info.nightscout.androidaps.plugins.DanaR.comm.MsgError;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.DeviceStatus; import info.nightscout.androidaps.plugins.Loop.DeviceStatus;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResult; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog; import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.Notification;
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.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.client.data.DbLogger; import info.nightscout.client.data.DbLogger;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -647,7 +647,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
emptyDescription.isBolusCapable = false; emptyDescription.isBolusCapable = false;
emptyDescription.isExtendedBolusCapable = false; emptyDescription.isExtendedBolusCapable = false;
emptyDescription.isSetBasalProfileCapable = false; emptyDescription.isSetBasalProfileCapable = false;
emptyDescription.isTempBasalCapable = false; emptyDescription.isTempBasalCapable = true; // needs to be true before real driver is selected
emptyDescription.isRefillingCapable = false; emptyDescription.isRefillingCapable = false;
return emptyDescription; return emptyDescription;
} }
@ -697,7 +697,8 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
@Override @Override
public boolean isAMAModeEnabled() { public boolean isAMAModeEnabled() {
boolean result = true; SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
boolean result = preferences.getBoolean("openapsama_useautosens", false);
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) { for (PluginBase p : constraintsPlugins) {
@ -901,8 +902,14 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun)); apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun));
deviceStatus.suggested = apsResult.json(); deviceStatus.suggested = apsResult.json();
if (lastRun.request instanceof DetermineBasalResult) { if (lastRun.request instanceof DetermineBasalResultMA) {
DetermineBasalResult result = (DetermineBasalResult) lastRun.request; DetermineBasalResultMA result = (DetermineBasalResultMA) lastRun.request;
deviceStatus.iob = result.iob.json();
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
}
if (lastRun.request instanceof DetermineBasalResultAMA) {
DetermineBasalResultAMA result = (DetermineBasalResultAMA) lastRun.request;
deviceStatus.iob = result.iob.json(); deviceStatus.iob = result.iob.json();
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun)); deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
} }
@ -974,7 +981,25 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString(), NewExtendedBolusDialog.class); DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void removeCareportalEntryFromNS(String _id) {
try {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbRemove");
bundle.putString("collection", "treatments");
bundle.putString("_id", _id);
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
DbLogger.dbRemove(intent, _id, ConfigBuilderPlugin.class);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -21,7 +22,7 @@ public class MsgSetExtendedBolusStart extends MessageBase {
if (halfhours > 16) halfhours = 16; if (halfhours > 16) halfhours = 16;
amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
if (amount < 0d) amount = 0d; if (amount < 0d) amount = 0d;
if (amount > 10d) amount = 10d; if (amount > BuildConfig.MAXBOLUS) amount = BuildConfig.MAXBOLUS;
AddParamInt((int) (amount * 100)); AddParamInt((int) (amount * 100));
AddParamByte(halfhours); AddParamByte(halfhours);

View file

@ -106,7 +106,7 @@ public class LocalProfileFragment extends Fragment implements FragmentBase {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
profileswitch.executeProfileSwitch = true; profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch); newDialog.setOptions(profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");

View file

@ -16,7 +16,7 @@ import info.nightscout.utils.DecimalFormatter;
/** /**
* Created by mike on 09.06.2016. * Created by mike on 09.06.2016.
*/ */
public class APSResult implements Parcelable { public class APSResult {
public String reason; public String reason;
public double rate; public double rate;
public int duration; public int duration;
@ -51,36 +51,6 @@ public class APSResult implements Parcelable {
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested)); return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
} }
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(reason);
dest.writeDouble(rate);
dest.writeInt(duration);
dest.writeInt(changeRequested ? 1 : 0);
}
public final Parcelable.Creator<APSResult> CREATOR = new Parcelable.Creator<APSResult>() {
public APSResult createFromParcel(Parcel in) {
return new APSResult(in);
}
public APSResult[] newArray(int size) {
return new APSResult[size];
}
};
protected APSResult(Parcel in) {
reason = in.readString();
rate = in.readDouble();
duration = in.readInt();
changeRequested = in.readInt() == 1;
}
public APSResult() { public APSResult() {
} }

View file

@ -76,7 +76,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Frag
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.loop_run: case R.id.loop_run:
getPlugin().invoke(true); getPlugin().invoke("Loop button", true);
break; break;
} }

View file

@ -108,15 +108,15 @@ public class LoopPlugin implements PluginBase {
@Subscribe @Subscribe
public void onStatusEvent(final EventTreatmentChange ev) { public void onStatusEvent(final EventTreatmentChange ev) {
invoke(true); invoke("EventTreatmentChange", true);
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventNewBG ev) { public void onStatusEvent(final EventNewBG ev) {
invoke(true); invoke("EventNewBG", true);
} }
public void invoke(boolean allowNotification) { public void invoke(String initiator, boolean allowNotification) {
try { try {
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
log.debug("invoke"); log.debug("invoke");
@ -136,7 +136,7 @@ public class LoopPlugin implements PluginBase {
APSInterface usedAPS = configBuilder.getActiveAPS(); APSInterface usedAPS = configBuilder.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) { if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) {
usedAPS.invoke(); usedAPS.invoke(initiator);
result = usedAPS.getLastAPSResult(); result = usedAPS.getLastAPSResult();
} }

View file

@ -177,7 +177,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
MainApp.sResources.getString(R.string.objectives_6_objective), MainApp.sResources.getString(R.string.objectives_6_objective),
"", "",
new Date(0), new Date(0),
1, 14,
new Date(0))); new Date(0)));
} }

View file

@ -0,0 +1,225 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.Round;
public class Autosens {
private static Logger log = LoggerFactory.getLogger(Autosens.class);
public static AutosensResult detectSensitivityandCarbAbsorption(List<BgReading> glucose_data, long mealTime) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
//console.error(mealTime);
double deviationSum = 0;
double carbsAbsorbed = 0;
List<BgReading> bucketed_data = new ArrayList<>();
bucketed_data.add(glucose_data.get(0));
int j = 0;
for (int i = 1; i < glucose_data.size(); ++i) {
long bgTime = glucose_data.get(i).getTimeIndex();
long lastbgTime = glucose_data.get(i - 1).getTimeIndex();
if (glucose_data.get(i).value < 39 || glucose_data.get(i - 1).value < 39) {
continue;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = glucose_data.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime + 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.timeIndex = nextbgTime;
double gapDelta = glucose_data.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5 / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
} else if (Math.abs(elapsed_minutes) > 2) {
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = glucose_data.get(i).value;
newBgreading.timeIndex = bgTime;
bucketed_data.add(newBgreading);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + glucose_data.get(i).value) / 2;
}
}
//console.error(bucketed_data);
double[] avgDeltas = new double[bucketed_data.size() - 2];
double[] bgis = new double[bucketed_data.size() - 2];
double[] deviations = new double[bucketed_data.size() - 2];
String debugString = "";
for (int i = 0; i < bucketed_data.size() - 3; ++i) {
long bgTime = bucketed_data.get(i).timeIndex;
int secondsFromMidnight = NSProfile.secondsFromMidnight(new Date(bgTime));
double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits());
//console.error(bgTime , bucketed_data[i].glucose);
double bg;
double avgDelta;
double delta;
bg = bucketed_data.get(i).value;
if (bg < 40 || bucketed_data.get(i + 3).value < 40) {
log.error("! value < 40");
continue;
}
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
delta = (bg - bucketed_data.get(i + 1).value);
// avgDelta = avgDelta.toFixed(2);
IobTotal iob = IobTotal.calulateFromTreatmentsAndTemps(bgTime);
double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100;
// bgi = bgi.toFixed(2);
//console.error(delta);
double deviation = delta - bgi;
// deviation = deviation.toFixed(2);
//if (deviation < 0 && deviation > -2) { console.error("BG: "+bg+", avgDelta: "+avgDelta+", BGI: "+bgi+", deviation: "+deviation); }
// Exclude large positive deviations (carb absorption) from autosens
if (avgDelta - bgi < 6) {
if (deviation > 0) {
debugString += "+";
} else if (deviation == 0) {
debugString += "=";
} else {
debugString += "-";
}
avgDeltas[i] = avgDelta;
bgis[i] = bgi;
deviations[i] = deviation;
deviationSum += deviation;
} else {
debugString += ">";
//console.error(bgTime);
}
// if bgTime is more recent than mealTime
if (bgTime > mealTime) {
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption
double ci = Math.max(deviation, Constants.MIN_5M_CARBIMPACT);
double absorbed = ci * profile.getIc(secondsFromMidnight) / sens;
// and add that to the running total carbsAbsorbed
carbsAbsorbed += absorbed;
}
}
//console.error("");
log.debug(debugString);
//console.log(JSON.stringify(avgDeltas));
//console.log(JSON.stringify(bgis));
Arrays.sort(avgDeltas);
Arrays.sort(bgis);
Arrays.sort(deviations);
for (double i = 0.9; i > 0.1; i = i - 0.02) {
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
}
}
double pSensitive = percentile(deviations, 0.50);
double pResistant = percentile(deviations, 0.45);
//p30 = percentile(deviations, 0.3);
// average = deviationSum / deviations.length;
//console.error("Mean deviation: "+average.toFixed(2));
double basalOff = 0;
if (pSensitive < 0) { // sensitive
basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
log.debug("Excess insulin sensitivity detected: ");
} else if (pResistant > 0) { // resistant
basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
log.debug("Excess insulin resistance detected: ");
} else {
log.debug("Sensitivity normal.");
}
double ratio = 1 + (basalOff / profile.getMaxDailyBasal());
// don't adjust more than 1.5x
double rawRatio = ratio;
ratio = Math.max(ratio, Constants.AUTOSENS_MIN);
ratio = Math.min(ratio, Constants.AUTOSENS_MAX);
if (ratio != rawRatio) {
log.debug("Ratio limited from " + rawRatio + " to " + ratio);
}
double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio);
if (ratio != 1) {
log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf);
}
//console.error("Basal adjustment "+basalOff.toFixed(2)+"U/hr");
//console.error("Ratio: "+ratio*100+"%: new ISF: "+newisf.toFixed(1)+"mg/dL/U");
AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01);
output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
return output;
}
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
public static double percentile(double[] arr, double p) {
if (arr.length == 0) return 0;
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
double index = arr.length * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[(int) lower];
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
}
// Returns the percentile of the given value in a sorted numeric array.
public static double percentRank(double[] arr, double v) {
for (int i = 0, l = arr.length; i < l; i++) {
if (v <= arr[i]) {
while (i < l && v == arr[i]) i++;
if (i == 0) return 0;
if (v != arr[i - 1]) {
i += (v - arr[i - 1]) / (arr[i] - arr[i - 1]);
}
return i / l;
}
}
return 1;
}
}

View file

@ -0,0 +1,9 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
/**
* Created by mike on 06.01.2017.
*/
public class AutosensResult {
public double ratio;
public double carbsAbsorbed;
}

View file

@ -0,0 +1,292 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import com.eclipsesource.v8.JavaVoidCallback;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8Object;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile;
public class DetermineBasalAdapterAMAJS {
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterAMAJS.class);
private ScriptReader mScriptReader = null;
V8 mV8rt;
private V8Object mProfile;
private V8Object mGlucoseStatus;
private V8Array mIobData;
private V8Object mMealData;
private V8Object mCurrentTemp;
private V8Object mAutosensData = null;
private final String PARAM_currentTemp = "currentTemp";
private final String PARAM_iobData = "iobData";
private final String PARAM_glucoseStatus = "glucose_status";
private final String PARAM_profile = "profile";
private final String PARAM_meal_data = "meal_data";
private final String PARAM_autosens_data = "autosens_data";
private String storedCurrentTemp = null;
private String storedIobData = null;
private String storedGlucoseStatus = null;
private String storedProfile = null;
private String storedMeal_data = null;
private String storedAutosens_data = null;
private String scriptDebug = "";
/**
* Main code
*/
public DetermineBasalAdapterAMAJS(ScriptReader scriptReader) throws IOException {
mV8rt = V8.createV8Runtime();
mScriptReader = scriptReader;
initLogCallback();
initProcessExitCallback();
initModuleParent();
loadScript();
}
public DetermineBasalResultAMA invoke() {
log.debug(">>> Invoking detemine_basal <<<");
log.debug("Glucose status: " + (storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");")));
log.debug("IOB data: " + (storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");")));
log.debug("Current temp: " + (storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");")));
log.debug("Profile: " + (storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");")));
log.debug("Meal data: " + (storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");")));
if (mAutosensData != null)
log.debug("Autosens data: " + (storedAutosens_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_autosens_data + ");")));
else
log.debug("Autosens data: " + (storedAutosens_data = "undefined"));
mV8rt.executeVoidScript(
"var rT = determine_basal(" +
PARAM_glucoseStatus + ", " +
PARAM_currentTemp + ", " +
PARAM_iobData + ", " +
PARAM_profile + ", " +
PARAM_autosens_data + ", " +
PARAM_meal_data + ", " +
"tempBasalFunctions" +
");");
String ret = mV8rt.executeStringScript("JSON.stringify(rT);");
log.debug("Result: " + ret);
V8Object v8ObjectReuslt = mV8rt.getObject("rT");
DetermineBasalResultAMA result = null;
try {
result = new DetermineBasalResultAMA(v8ObjectReuslt, new JSONObject(ret));
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
String getGlucoseStatusParam() {
return storedGlucoseStatus;
}
String getCurrentTempParam() {
return storedCurrentTemp;
}
String getIobDataParam() {
return storedIobData;
}
String getProfileParam() {
return storedProfile;
}
String getMealDataParam() {
return storedMeal_data;
}
String getAutosensDataParam() {
return storedAutosens_data;
}
String getScriptDebug() {
return scriptDebug;
}
private void loadScript() throws IOException {
mV8rt.executeVoidScript(readFile("OpenAPSAMA/round-basal.js"), "OpenAPSAMA/round-basal.js", 0);
mV8rt.executeVoidScript("var round_basal = module.exports;");
mV8rt.executeVoidScript("require = function() {return round_basal;};");
mV8rt.executeVoidScript(readFile("OpenAPSAMA/basal-set-temp.js"), "OpenAPSAMA/basal-set-temp.js ", 0);
mV8rt.executeVoidScript("var tempBasalFunctions = module.exports;");
mV8rt.executeVoidScript(
readFile("OpenAPSAMA/determine-basal.js"),
"OpenAPSAMA/determine-basal.js",
0);
mV8rt.executeVoidScript("var determine_basal = module.exports;");
mV8rt.executeVoidScript(
"var setTempBasal = function (rate, duration, profile, rT, offline) {" +
"rT.duration = duration;\n" +
" rT.rate = rate;" +
"return rT;" +
"};",
"setTempBasal.js",
0
);
}
private void initModuleParent() {
mV8rt.executeVoidScript("var module = {\"parent\":Boolean(1)};");
}
private void initProcessExitCallback() {
JavaVoidCallback callbackProccessExit = new JavaVoidCallback() {
@Override
public void invoke(V8Object arg0, V8Array parameters) {
if (parameters.length() > 0) {
Object arg1 = parameters.get(0);
log.error("ProccessExit " + arg1);
}
}
};
mV8rt.registerJavaMethod(callbackProccessExit, "proccessExit");
mV8rt.executeVoidScript("var process = {\"exit\": function () { proccessExit(); } };");
}
private void initLogCallback() {
JavaVoidCallback callbackLog = new JavaVoidCallback() {
@Override
public void invoke(V8Object arg0, V8Array parameters) {
int i = 0;
String s = "";
while (i < parameters.length()) {
Object arg = parameters.get(i);
s += arg + " ";
i++;
}
if (!s.equals("") && Config.logAPSResult) {
log.debug("Script debug: " + s);
scriptDebug += s + "\n";
}
}
};
mV8rt.registerJavaMethod(callbackLog, "log");
mV8rt.executeVoidScript("var console = {\"log\":log, \"error\":log};");
}
public void setData(NSProfile profile,
double maxIob,
double maxBasal,
double minBg,
double maxBg,
double targetBg,
PumpInterface pump,
IobTotal[] iobArray,
GlucoseStatus glucoseStatus,
MealData mealData,
double autosensDataRatio,
boolean tempTargetSet,
double min_5m_carbimpact) {
String units = profile.getUnits();
mProfile = new V8Object(mV8rt);
mProfile.add("max_iob", maxIob);
mProfile.add("carbs_hr", profile.getCarbAbsorbtionRate());
mProfile.add("dia", profile.getDia());
mProfile.add("type", "current");
mProfile.add("max_daily_basal", profile.getMaxDailyBasal());
mProfile.add("max_basal", maxBasal);
mProfile.add("min_bg", minBg);
mProfile.add("max_bg", maxBg);
mProfile.add("target_bg", targetBg);
mProfile.add("carb_ratio", profile.getIc(profile.secondsFromMidnight()));
mProfile.add("sens", NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units));
mProfile.add("max_daily_safety_multiplier", Constants.MAX_DAILY_SAFETY_MULTIPLIER);
mProfile.add("current_basal_safety_multiplier", Constants.CURRENT_BASAL_SAFETY_MULTIPLIER);
mProfile.add("skip_neutral_temps", true);
mProfile.add("current_basal", pump.getBaseBasalRate());
mProfile.add("temptargetSet", tempTargetSet);
mProfile.add("autosens_adjust_targets", Constants.AUTOSENS_ADJUST_TARGETS);
mProfile.add("min_5m_carbimpact", min_5m_carbimpact);
mV8rt.add(PARAM_profile, mProfile);
mCurrentTemp = new V8Object(mV8rt);
mCurrentTemp.add("temp", "absolute");
mCurrentTemp.add("duration", pump.getTempBasalRemainingMinutes());
mCurrentTemp.add("rate", pump.getTempBasalAbsoluteRate());
mV8rt.add(PARAM_currentTemp, mCurrentTemp);
mIobData = mV8rt.executeArrayScript(IobTotal.convertToJSONArray(iobArray).toString());
mV8rt.add(PARAM_iobData, mIobData);
mGlucoseStatus = new V8Object(mV8rt);
mGlucoseStatus.add("glucose", glucoseStatus.glucose);
mGlucoseStatus.add("delta", glucoseStatus.delta);
mGlucoseStatus.add("short_avgdelta", glucoseStatus.short_avgdelta);
mGlucoseStatus.add("long_avgdelta", glucoseStatus.long_avgdelta);
mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus);
mMealData = new V8Object(mV8rt);
mMealData.add("carbs", mealData.carbs);
mMealData.add("boluses", mealData.boluses);
mMealData.add("mealCOB", mealData.mealCOB);
mV8rt.add(PARAM_meal_data, mMealData);
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
mAutosensData = new V8Object(mV8rt);
mAutosensData.add("ratio", autosensDataRatio);
mV8rt.add(PARAM_autosens_data, mAutosensData);
} else {
mV8rt.addUndefined(PARAM_autosens_data);
}
}
public void release() {
mProfile.release();
mCurrentTemp.release();
mIobData.release();
mMealData.release();
mGlucoseStatus.release();
if (mAutosensData != null) {
mAutosensData.release();
}
mV8rt.release();
}
public String readFile(String filename) throws IOException {
byte[] bytes = mScriptReader.readFile(filename);
String string = new String(bytes, "UTF-8");
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20);
}
return string;
}
}

View file

@ -0,0 +1,159 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import android.os.Parcel;
import android.os.Parcelable;
import com.eclipsesource.v8.V8Object;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.data.IobTotal;
public class DetermineBasalResultAMA extends APSResult {
public Date date;
public JSONObject json = new JSONObject();
public double eventualBG;
public double snoozeBG;
public IobTotal iob;
public DetermineBasalResultAMA(V8Object result, JSONObject j) {
date = new Date();
json = j;
if (result.contains("error")) {
reason = result.getString("error");
changeRequested = false;
rate = -1;
duration = -1;
} else {
reason = result.getString("reason");
eventualBG = result.getDouble("eventualBG");
snoozeBG = result.getDouble("snoozeBG");
if (result.contains("rate")) {
rate = result.getDouble("rate");
if (rate < 0d) rate = 0d;
changeRequested = true;
} else {
rate = -1;
changeRequested = false;
}
if (result.contains("duration")) {
duration = result.getInteger("duration");
changeRequested = changeRequested;
} else {
duration = -1;
changeRequested = false;
}
}
result.release();
}
public DetermineBasalResultAMA() {
}
@Override
public DetermineBasalResultAMA clone() {
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
newResult.reason = new String(reason);
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
try {
newResult.json = new JSONObject(json.toString());
} catch (JSONException e) {
e.printStackTrace();
}
newResult.eventualBG = eventualBG;
newResult.snoozeBG = snoozeBG;
newResult.date = date;
return newResult;
}
@Override
public JSONObject json() {
try {
JSONObject ret = new JSONObject(this.json.toString());
return ret;
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
public List<BgReading> getPredictions() {
List<BgReading> array = new ArrayList<>();
try {
long startTime = date.getTime();
if (json.has("predBGs")) {
JSONObject predBGs = json.getJSONObject("predBGs");
if (predBGs.has("IOB")) {
JSONArray iob = predBGs.getJSONArray("IOB");
for (int i = 1; i < iob.length(); i ++) {
BgReading bg = new BgReading();
bg.value = iob.getInt(i);
bg.timeIndex = startTime + i * 5 * 60 * 1000L;
array.add(bg);
}
}
if (predBGs.has("aCOB")) {
JSONArray iob = predBGs.getJSONArray("aCOB");
for (int i = 1; i < iob.length(); i ++) {
BgReading bg = new BgReading();
bg.value = iob.getInt(i);
bg.timeIndex = startTime + i * 5 * 60 * 1000L;
array.add(bg);
}
}
if (predBGs.has("COB")) {
JSONArray iob = predBGs.getJSONArray("COB");
for (int i = 1; i < iob.length(); i ++) {
BgReading bg = new BgReading();
bg.value = iob.getInt(i);
bg.timeIndex = startTime + i * 5 * 60 * 1000L;
array.add(bg);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return array;
}
public long getLatestPredictionsTime() {
long latest = 0;
try {
long startTime = date.getTime();
if (json.has("predBGs")) {
JSONObject predBGs = json.getJSONObject("predBGs");
if (predBGs.has("IOB")) {
JSONArray iob = predBGs.getJSONArray("IOB");
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
}
if (predBGs.has("aCOB")) {
JSONArray iob = predBGs.getJSONArray("aCOB");
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
}
if (predBGs.has("COB")) {
JSONArray iob = predBGs.getJSONArray("COB");
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return latest;
}
}

View file

@ -0,0 +1,157 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.utils.JSONFormatter;
public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
private static Logger log = LoggerFactory.getLogger(OpenAPSAMAFragment.class);
private static OpenAPSAMAPlugin openAPSAMAPlugin;
public static OpenAPSAMAPlugin getPlugin() {
if(openAPSAMAPlugin ==null){
openAPSAMAPlugin = new OpenAPSAMAPlugin();
}
return openAPSAMAPlugin;
}
Button run;
TextView lastRunView;
TextView glucoseStatusView;
TextView currentTempView;
TextView iobDataView;
TextView profileView;
TextView mealDataView;
TextView autosensDataView;
TextView resultView;
TextView scriptdebugView;
TextView requestView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.openapsama_fragment, container, false);
run = (Button) view.findViewById(R.id.openapsma_run);
run.setOnClickListener(this);
lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun);
glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus);
currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp);
iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata);
profileView = (TextView) view.findViewById(R.id.openapsma_profile);
mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata);
autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata);
scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata);
resultView = (TextView) view.findViewById(R.id.openapsma_result);
requestView = (TextView) view.findViewById(R.id.openapsma_request);
updateGUI();
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.openapsma_run:
getPlugin().invoke("OpenAPSAMA button");
break;
}
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Override
public void onResume() {
super.onResume();
MainApp.bus().register(this);
}
@Subscribe
public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
updateGUI();
}
@Subscribe
public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
updateResultGUI(ev.text);
}
void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
DetermineBasalResultAMA lastAPSResult = getPlugin().lastAPSResult;
if (lastAPSResult != null) {
resultView.setText(JSONFormatter.format(lastAPSResult.json));
requestView.setText(lastAPSResult.toSpanned());
}
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = getPlugin().lastDetermineBasalAdapterAMAJS;
if (determineBasalAdapterAMAJS != null) {
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getGlucoseStatusParam()));
currentTempView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getCurrentTempParam()));
try {
JSONArray iobArray = new JSONArray(determineBasalAdapterAMAJS.getIobDataParam());
iobDataView.setText(String.format(MainApp.sResources.getString(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0)));
} catch (JSONException e) {
e.printStackTrace();
iobDataView.setText("JSONException");
}
profileView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getProfileParam()));
mealDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getMealDataParam()));
autosensDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getAutosensDataParam()));
scriptdebugView.setText(determineBasalAdapterAMAJS.getScriptDebug());
}
if (getPlugin().lastAPSRun != null) {
lastRunView.setText(getPlugin().lastAPSRun.toLocaleString());
}
}
});
}
void updateResultGUI(final String text) {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
resultView.setText(text);
glucoseStatusView.setText("");
currentTempView.setText("");
iobDataView.setText("");
profileView.setText("");
mealDataView.setText("");
autosensDataView.setText("");
scriptdebugView.setText("");
requestView.setText("");
lastRunView.setText("");
}
});
}
}

View file

@ -0,0 +1,261 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
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.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
/**
* Created by mike on 05.08.2016.
*/
public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
private static Logger log = LoggerFactory.getLogger(OpenAPSAMAPlugin.class);
// last values
DetermineBasalAdapterAMAJS lastDetermineBasalAdapterAMAJS = null;
Date lastAPSRun = null;
DetermineBasalResultAMA lastAPSResult = null;
boolean fragmentEnabled = false;
boolean fragmentVisible = true;
@Override
public String getName() {
return MainApp.instance().getString(R.string.openapsama);
}
@Override
public boolean isEnabled(int type) {
return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == APS) this.fragmentVisible = fragmentVisible;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == APS) this.fragmentEnabled = fragmentEnabled;
}
@Override
public int getType() {
return PluginBase.APS;
}
@Override
public String getFragmentClass() {
return OpenAPSAMAFragment.class.getName();
}
@Override
public APSResult getLastAPSResult() {
return lastAPSResult;
}
@Override
public Date getLastAPSRun() {
return lastAPSRun;
}
@Override
public void invoke(String initiator) {
log.debug("invoke from " + initiator);
lastAPSResult = null;
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = null;
try {
determineBasalAdapterAMAJS = new DetermineBasalAdapterAMAJS(new ScriptReader(MainApp.instance().getBaseContext()));
} catch (IOException e) {
log.error(e.getMessage(), e);
return;
}
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
PumpInterface pump = MainApp.getConfigBuilder();
if (!isEnabled(PluginBase.APS)) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_disabled));
return;
}
if (glucoseStatus == null) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata));
return;
}
if (profile == null) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile)));
if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_noprofile));
return;
}
if (pump == null) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump)));
if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_nopump));
return;
}
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
String units = profile.getUnits();
String maxBgDefault = "180";
String minBgDefault = "100";
String targetBgDefault = "150";
if (!units.equals(Constants.MGDL)) {
maxBgDefault = "10";
minBgDefault = "5";
targetBgDefault = "7";
}
Date now = new Date();
double maxIob = SafeParse.stringToDouble(SP.getString("openapsma_max_iob", "1.5"));
double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
double minBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_min_bg", minBgDefault)), units);
double maxBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_max_bg", maxBgDefault)), units);
double targetBg = NSProfile.toMgdl(SafeParse.stringToDouble(SP.getString("openapsma_target_bg", targetBgDefault)), units);
minBg = Round.roundTo(minBg, 0.1d);
maxBg = Round.roundTo(maxBg, 0.1d);
IobTotal[] iobArray = IobTotal.calculateIobArrayInDia();
MealData mealData = MainApp.getConfigBuilder().getActiveTreatments().getMealData();
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
minBg = verifyHardLimits(minBg, "minBg", 72, 180);
maxBg = verifyHardLimits(maxBg, "maxBg", 100, 270);
targetBg = verifyHardLimits(targetBg, "targetBg", 80, 200);
boolean isTempTarget = false;
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
if (tempTarget != null) {
isTempTarget = true;
minBg = verifyHardLimits(tempTarget.low, "minBg", 72, 180);
maxBg = verifyHardLimits(tempTarget.high, "maxBg", 72, 270);
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", 72, 200);
}
}
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
if (!checkOnlyHardLimits(profile.getCarbAbsorbtionRate(), "carbs_hr", 4, 100)) return;
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100)) return;
if (!checkOnlyHardLimits(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units), "sens", 2, 900)) return;
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
long oldestDataAvailable = MainApp.getConfigBuilder().getActiveTempBasals().oldestDataAvaialable();
List<BgReading> bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(Math.max(oldestDataAvailable, (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia()))), false);
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString() + " (" + bgReadings.size() + " records)");
AutosensResult autosensResult = Autosens.detectSensitivityandCarbAbsorption(bgReadings, new Date().getTime());
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData,
autosensResult.ratio, //autosensDataRatio
isTempTarget,
Constants.MIN_5M_CARBIMPACT //min_5m_carbimpact
);
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();
// Fix bug determine basal
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultAMA.changeRequested = false;
// limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1)
determineBasalResultAMA.changeRequested = false;
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1)
determineBasalResultAMA.changeRequested = false;
}
determineBasalResultAMA.iob = iobArray[0];
determineBasalAdapterAMAJS.release();
try {
determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now));
} catch (JSONException e) {
e.printStackTrace();
}
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS;
lastAPSResult = determineBasalResultAMA;
lastAPSRun = now;
MainApp.bus().post(new EventOpenAPSUpdateGui());
//deviceStatus.suggested = determineBasalResultAMA.json;
}
// safety checks
public static boolean checkOnlyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
return value.equals(verifyHardLimits(value, valueName, lowLimit, highLimit));
}
public static Double verifyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
if (value < lowLimit || value > highLimit) {
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), valueName);
log.error(msg);
MainApp.getConfigBuilder().uploadError(msg);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
value = Math.max(value, lowLimit);
value = Math.min(value, highLimit);
}
return value;
}
}

View file

@ -1,8 +1,5 @@
package info.nightscout.androidaps.plugins.OpenAPSMA; package info.nightscout.androidaps.plugins.OpenAPSMA;
import android.os.Parcel;
import android.os.Parcelable;
import com.eclipsesource.v8.JavaVoidCallback; import com.eclipsesource.v8.JavaVoidCallback;
import com.eclipsesource.v8.V8; import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array; import com.eclipsesource.v8.V8Array;
@ -16,15 +13,15 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
public class DetermineBasalAdapterJS implements Parcelable { public class DetermineBasalAdapterMAJS {
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterJS.class); private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterMAJS.class);
private ScriptReader mScriptReader = null; private ScriptReader mScriptReader = null;
@ -47,49 +44,11 @@ public class DetermineBasalAdapterJS implements Parcelable {
private String storedProfile = null; private String storedProfile = null;
private String storedMeal_data = null; private String storedMeal_data = null;
/** /**
* Parcelable implementation
* result string for display only
**/
protected DetermineBasalAdapterJS(Parcel in) {
storedCurrentTemp = in.readString();
storedIobData = in.readString();
storedGlucoseStatus = in.readString();
storedProfile = in.readString();
storedMeal_data = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(storedCurrentTemp);
dest.writeString(storedIobData);
dest.writeString(storedGlucoseStatus);
dest.writeString(storedProfile);
dest.writeString(storedMeal_data);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<DetermineBasalAdapterJS> CREATOR = new Creator<DetermineBasalAdapterJS>() {
@Override
public DetermineBasalAdapterJS createFromParcel(Parcel in) {
return new DetermineBasalAdapterJS(in);
}
@Override
public DetermineBasalAdapterJS[] newArray(int size) {
return new DetermineBasalAdapterJS[size];
}
};
/**
* Main code * Main code
*/ */
public DetermineBasalAdapterJS(ScriptReader scriptReader) throws IOException { public DetermineBasalAdapterMAJS(ScriptReader scriptReader) throws IOException {
mV8rt = V8.createV8Runtime(); mV8rt = V8.createV8Runtime();
mScriptReader = scriptReader; mScriptReader = scriptReader;
@ -143,7 +102,7 @@ public class DetermineBasalAdapterJS implements Parcelable {
mV8rt.add(PARAM_meal_data, mMealData); mV8rt.add(PARAM_meal_data, mMealData);
} }
public DetermineBasalResult invoke() { public DetermineBasalResultMA invoke() {
mV8rt.executeVoidScript( mV8rt.executeVoidScript(
"console.error(\"determine_basal(\"+\n" + "console.error(\"determine_basal(\"+\n" +
"JSON.stringify(" + PARAM_glucoseStatus + ")+ \", \" +\n" + "JSON.stringify(" + PARAM_glucoseStatus + ")+ \", \" +\n" +
@ -170,14 +129,13 @@ public class DetermineBasalAdapterJS implements Parcelable {
V8Object v8ObjectReuslt = mV8rt.getObject("rT"); V8Object v8ObjectReuslt = mV8rt.getObject("rT");
DetermineBasalResult result = null; DetermineBasalResultMA result = null;
try { try {
result = new DetermineBasalResult(v8ObjectReuslt, new JSONObject(ret)); result = new DetermineBasalResultMA(v8ObjectReuslt, new JSONObject(ret));
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
// Store input params for Parcelable
storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");"); storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");");
storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");"); storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");");
storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");"); storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");");
@ -266,8 +224,8 @@ public class DetermineBasalAdapterJS implements Parcelable {
double targetBg, double targetBg,
PumpInterface pump, PumpInterface pump,
IobTotal iobData, IobTotal iobData,
DatabaseHelper.GlucoseStatus glucoseStatus, GlucoseStatus glucoseStatus,
TreatmentsPlugin.MealData mealData) { MealData mealData) {
String units = profile.getUnits(); String units = profile.getUnits();

View file

@ -8,9 +8,10 @@ import com.eclipsesource.v8.V8Object;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
public class DetermineBasalResult extends APSResult { public class DetermineBasalResultMA extends APSResult {
public JSONObject json = new JSONObject(); public JSONObject json = new JSONObject();
public double eventualBG; public double eventualBG;
@ -18,7 +19,7 @@ public class DetermineBasalResult extends APSResult {
public String mealAssist; public String mealAssist;
public IobTotal iob; public IobTotal iob;
public DetermineBasalResult(V8Object result, JSONObject j) { public DetermineBasalResultMA(V8Object result, JSONObject j) {
json = j; json = j;
if (result.contains("error")) { if (result.contains("error")) {
reason = result.getString("error"); reason = result.getString("error");
@ -52,43 +53,12 @@ public class DetermineBasalResult extends APSResult {
result.release(); result.release();
} }
@Override public DetermineBasalResultMA() {
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(json.toString());
dest.writeDouble(eventualBG);
dest.writeDouble(snoozeBG);
dest.writeString(mealAssist);
}
public final Parcelable.Creator<DetermineBasalResult> CREATOR = new Parcelable.Creator<DetermineBasalResult>() {
public DetermineBasalResult createFromParcel(Parcel in) {
return new DetermineBasalResult(in);
}
public DetermineBasalResult[] newArray(int size) {
return new DetermineBasalResult[size];
}
};
private DetermineBasalResult(Parcel in) {
super(in);
try {
json = new JSONObject(in.readString());
} catch (JSONException e) {
e.printStackTrace();
}
eventualBG = in.readDouble();
snoozeBG = in.readDouble();
mealAssist = in.readString();
}
public DetermineBasalResult() {
} }
@Override @Override
public DetermineBasalResult clone() { public DetermineBasalResultMA clone() {
DetermineBasalResult newResult = new DetermineBasalResult(); DetermineBasalResultMA newResult = new DetermineBasalResultMA();
newResult.reason = new String(reason); newResult.reason = new String(reason);
newResult.rate = rate; newResult.rate = rate;
newResult.duration = duration; newResult.duration = duration;

View file

@ -1,76 +0,0 @@
package info.nightscout.androidaps.plugins.OpenAPSMA;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
public class IobTotal {
public Double iob;
public Double activity;
public Double bolussnooze;
public Double basaliob;
public Double netbasalinsulin;
public Double hightempinsulin;
public Double netInsulin = 0d; // for calculations from temp basals only
public Double netRatio = 0d; // for calculations from temp basals only
public IobTotal() {
this.iob = 0d;
this.activity = 0d;
this.bolussnooze = 0d;
this.basaliob = 0d;
this.netbasalinsulin = 0d;
this.hightempinsulin = 0d;
}
public IobTotal plus(IobTotal other) {
iob += other.iob;
activity += other.activity;
bolussnooze += other.bolussnooze;
basaliob += other.basaliob;
netbasalinsulin += other.netbasalinsulin;
hightempinsulin += other.hightempinsulin;
netInsulin += other.netInsulin;
netRatio += other.netRatio;
return this;
}
public static IobTotal combine(IobTotal bolusIOB, IobTotal basalIob) {
IobTotal result = new IobTotal();
result.iob = bolusIOB.iob + basalIob.basaliob;
result.activity = bolusIOB.activity + basalIob.activity;
result.bolussnooze = bolusIOB.bolussnooze;
result.basaliob = basalIob.basaliob;
result.netbasalinsulin = basalIob.netbasalinsulin;
result.hightempinsulin = basalIob.hightempinsulin;
return result;
}
public IobTotal round() {
this.iob = Round.roundTo(this.iob, 0.001);
this.activity = Round.roundTo(this.activity, 0.0001);
this.bolussnooze = Round.roundTo(this.bolussnooze, 0.0001);
this.basaliob = Round.roundTo(this.basaliob, 0.001);
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
return this;
}
public JSONObject json() {
JSONObject json = new JSONObject();
try {
json.put("iob", iob);
json.put("basaliob", basaliob);
json.put("activity", activity);
json.put("time", DateUtil.toISOString(new Date()));
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}

View file

@ -17,9 +17,8 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateResultGui;
import info.nightscout.utils.JSONFormatter; import info.nightscout.utils.JSONFormatter;
public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, FragmentBase { public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
@ -68,7 +67,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.openapsma_run: case R.id.openapsma_run:
getPlugin().invoke(); getPlugin().invoke("OpenAPSMA button");
break; break;
} }
@ -87,12 +86,12 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventOpenAPSMAUpdateGui ev) { public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
updateGUI(); updateGUI();
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventOpenAPSMAUpdateResultGui ev) { public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
updateResultGUI(ev.text); updateResultGUI(ev.text);
} }
@ -102,18 +101,18 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
DetermineBasalResult lastAPSResult = getPlugin().lastAPSResult; DetermineBasalResultMA lastAPSResult = getPlugin().lastAPSResult;
if (lastAPSResult != null) { if (lastAPSResult != null) {
resultView.setText(JSONFormatter.format(lastAPSResult.json)); resultView.setText(JSONFormatter.format(lastAPSResult.json));
requestView.setText(lastAPSResult.toSpanned()); requestView.setText(lastAPSResult.toSpanned());
} }
DetermineBasalAdapterJS determineBasalAdapterJS = getPlugin().lastDetermineBasalAdapterJS; DetermineBasalAdapterMAJS determineBasalAdapterMAJS = getPlugin().lastDetermineBasalAdapterMAJS;
if (determineBasalAdapterJS != null) { if (determineBasalAdapterMAJS != null) {
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterJS.getGlucoseStatusParam())); glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getGlucoseStatusParam()));
currentTempView.setText(JSONFormatter.format(determineBasalAdapterJS.getCurrentTempParam())); currentTempView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getCurrentTempParam()));
iobDataView.setText(JSONFormatter.format(determineBasalAdapterJS.getIobDataParam())); iobDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getIobDataParam()));
profileView.setText(JSONFormatter.format(determineBasalAdapterJS.getProfileParam())); profileView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getProfileParam()));
mealDataView.setText(JSONFormatter.format(determineBasalAdapterJS.getMealDataParam())); mealDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getMealDataParam()));
} }
if (getPlugin().lastAPSRun != null) { if (getPlugin().lastAPSRun != null) {
lastRunView.setText(getPlugin().lastAPSRun.toLocaleString()); lastRunView.setText(getPlugin().lastAPSRun.toLocaleString());

View file

@ -1,13 +1,9 @@
package info.nightscout.androidaps.plugins.OpenAPSMA; package info.nightscout.androidaps.plugins.OpenAPSMA;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -18,8 +14,10 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; 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.Services.Intents; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
@ -27,10 +25,9 @@ import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateResultGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.client.data.DbLogger;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
@ -44,9 +41,9 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
private static Logger log = LoggerFactory.getLogger(OpenAPSMAPlugin.class); private static Logger log = LoggerFactory.getLogger(OpenAPSMAPlugin.class);
// last values // last values
DetermineBasalAdapterJS lastDetermineBasalAdapterJS = null; DetermineBasalAdapterMAJS lastDetermineBasalAdapterMAJS = null;
Date lastAPSRun = null; Date lastAPSRun = null;
DetermineBasalResult lastAPSResult = null; DetermineBasalResultMA lastAPSResult = null;
boolean fragmentEnabled = false; boolean fragmentEnabled = false;
boolean fragmentVisible = true; boolean fragmentVisible = true;
@ -102,43 +99,44 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
} }
@Override @Override
public void invoke() { public void invoke(String initiator) {
log.debug("invoke from " + initiator);
lastAPSResult = null; lastAPSResult = null;
DetermineBasalAdapterJS determineBasalAdapterJS = null; DetermineBasalAdapterMAJS determineBasalAdapterMAJS = null;
try { try {
determineBasalAdapterJS = new DetermineBasalAdapterJS(new ScriptReader(MainApp.instance().getBaseContext())); determineBasalAdapterMAJS = new DetermineBasalAdapterMAJS(new ScriptReader(MainApp.instance().getBaseContext()));
} catch (IOException e) { } catch (IOException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return; return;
} }
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
PumpInterface pump = MainApp.getConfigBuilder(); PumpInterface pump = MainApp.getConfigBuilder();
if (!isEnabled(PluginBase.APS)) { if (!isEnabled(PluginBase.APS)) {
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
if (Config.logAPSResult) if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_disabled)); log.debug(MainApp.instance().getString(R.string.openapsma_disabled));
return; return;
} }
if (glucoseStatus == null) { if (glucoseStatus == null) {
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
if (Config.logAPSResult) if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata)); log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata));
return; return;
} }
if (profile == null) { if (profile == null) {
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile)));
if (Config.logAPSResult) if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_noprofile)); log.debug(MainApp.instance().getString(R.string.openapsma_noprofile));
return; return;
} }
if (pump == null) { if (pump == null) {
MainApp.bus().post(new EventOpenAPSMAUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump)));
if (Config.logAPSResult) if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_nopump)); log.debug(MainApp.instance().getString(R.string.openapsma_nopump));
return; return;
@ -176,13 +174,24 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
TreatmentsPlugin.MealData mealData = treatments.getMealData(); MealData mealData = treatments.getMealData();
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
minBg = verifyHardLimits(minBg, "minBg", 72, 180); minBg = verifyHardLimits(minBg, "minBg", 72, 180);
maxBg = verifyHardLimits(maxBg, "maxBg", 100, 270); maxBg = verifyHardLimits(maxBg, "maxBg", 100, 270);
targetBg = verifyHardLimits(targetBg, "targetBg", 80, 200); targetBg = verifyHardLimits(targetBg, "targetBg", 80, 200);
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
if (tempTarget != null) {
minBg = verifyHardLimits(tempTarget.low, "minBg", 72, 180);
maxBg = verifyHardLimits(tempTarget.high, "maxBg", 72, 270);
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", 72, 200);
}
}
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7); maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10); maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
@ -193,37 +202,37 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
determineBasalAdapterJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData); determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData);
DetermineBasalResult determineBasalResult = determineBasalAdapterJS.invoke(); DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
// Fix bug determine basal // Fix bug determine basal
if (determineBasalResult.rate == 0d && determineBasalResult.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress()) if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResult.changeRequested = false; determineBasalResultMA.changeRequested = false;
// limit requests on openloop mode // limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResult.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1) if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1)
determineBasalResult.changeRequested = false; determineBasalResultMA.changeRequested = false;
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResult.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1)
determineBasalResult.changeRequested = false; determineBasalResultMA.changeRequested = false;
} }
determineBasalResult.iob = iobTotal; determineBasalResultMA.iob = iobTotal;
determineBasalAdapterJS.release(); determineBasalAdapterMAJS.release();
try { try {
determineBasalResult.json.put("timestamp", DateUtil.toISOString(now)); determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now));
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
lastDetermineBasalAdapterJS = determineBasalAdapterJS; lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS;
lastAPSResult = determineBasalResult; lastAPSResult = determineBasalResultMA;
lastAPSRun = now; lastAPSRun = now;
MainApp.bus().post(new EventOpenAPSMAUpdateGui()); MainApp.bus().post(new EventOpenAPSUpdateGui());
//deviceStatus.suggested = determineBasalResult.json; //deviceStatus.suggested = determineBasalResultMA.json;
} }
// safety checks // safety checks

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventOpenAPSMAUpdateGui { public class EventOpenAPSUpdateGui {
} }

View file

@ -3,10 +3,10 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class EventOpenAPSMAUpdateResultGui { public class EventOpenAPSUpdateResultGui {
public String text = null; public String text = null;
public EventOpenAPSMAUpdateResultGui(String text) { public EventOpenAPSUpdateResultGui(String text) {
this.text = text; this.text = text;
} }
} }

View file

@ -38,18 +38,15 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.BolusWizard; import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.PlusMinusEditText; import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.Round;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;

View file

@ -20,6 +20,7 @@ public class Notification {
public static final int PROFILE_NOT_SET_NOT_INITIALIZED = 5; public static final int PROFILE_NOT_SET_NOT_INITIALIZED = 5;
public static final int FAILED_UDPATE_PROFILE = 6; public static final int FAILED_UDPATE_PROFILE = 6;
public static final int BASAL_VALUE_BELOW_MINIMUM = 7; public static final int BASAL_VALUE_BELOW_MINIMUM = 7;
public static final int OLD_NSCLIENT = 8;
public int id; public int id;
public Date date; public Date date;

View file

@ -22,6 +22,8 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
@ -49,10 +51,12 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; 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.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
@ -69,13 +73,16 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
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.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
import info.nightscout.androidaps.plugins.TempBasals.TempBasalsPlugin;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.BolusWizard; import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -105,7 +112,9 @@ public class OverviewFragment extends Fragment {
TextView activeProfileView; TextView activeProfileView;
TextView iobView; TextView iobView;
TextView apsModeView; TextView apsModeView;
TextView tempTargetView;
GraphView bgGraph; GraphView bgGraph;
CheckBox showPredictionView;
RecyclerView notificationsView; RecyclerView notificationsView;
LinearLayoutManager llm; LinearLayoutManager llm;
@ -152,6 +161,7 @@ public class OverviewFragment extends Fragment {
iobView = (TextView) view.findViewById(R.id.overview_iob); iobView = (TextView) view.findViewById(R.id.overview_iob);
apsModeView = (TextView) view.findViewById(R.id.overview_apsmode); apsModeView = (TextView) view.findViewById(R.id.overview_apsmode);
tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget);
bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph); bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph);
cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp);
treatmentButton = (Button) view.findViewById(R.id.overview_treatment); treatmentButton = (Button) view.findViewById(R.id.overview_treatment);
@ -162,12 +172,25 @@ public class OverviewFragment extends Fragment {
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard); quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard);
quickWizardLayout = (LinearLayout) view.findViewById(R.id.overview_quickwizardlayout); quickWizardLayout = (LinearLayout) view.findViewById(R.id.overview_quickwizardlayout);
showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction);
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications); notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
notificationsView.setHasFixedSize(true); notificationsView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext()); llm = new LinearLayoutManager(view.getContext());
notificationsView.setLayoutManager(llm); notificationsView.setLayoutManager(llm);
showPredictionView.setChecked(prefs.getBoolean("showprediction", false));
showPredictionView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("showprediction", showPredictionView.isChecked());
editor.apply();
updateGUI();
}
});
treatmentButton.setOnClickListener(new View.OnClickListener() { treatmentButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -214,7 +237,7 @@ public class OverviewFragment extends Fragment {
acceptTempButton.setOnClickListener(new View.OnClickListener() { acceptTempButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
MainApp.getConfigBuilder().getActiveLoop().invoke(false); MainApp.getConfigBuilder().getActiveLoop().invoke("Accept temp button", false);
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) { if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
@ -441,7 +464,7 @@ public class OverviewFragment extends Fragment {
updateNotifications(); updateNotifications();
BgReading actualBG = MainApp.getDbHelper().actualBg(); BgReading actualBG = MainApp.getDbHelper().actualBg();
BgReading lastBG = MainApp.getDbHelper().lastBg(); BgReading lastBG = MainApp.getDbHelper().lastBg();
if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null) // app not initialized yet if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null || MainApp.getConfigBuilder().getActiveProfile().getProfile() == null) // app not initialized yet
return; return;
// Skip if not initialized yet // Skip if not initialized yet
@ -497,8 +520,20 @@ public class OverviewFragment extends Fragment {
apsModeView.setVisibility(View.GONE); apsModeView.setVisibility(View.GONE);
} }
// **** Temp button **** // temp target
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
if (tempTarget != null) {
tempTargetView.setVisibility(View.VISIBLE);
tempTargetView.setText(NSProfile.toUnitsString(tempTarget.low, NSProfile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + NSProfile.toUnitsString(tempTarget.high, NSProfile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits()));
} else {
tempTargetView.setVisibility(View.GONE);
}
}
// **** Temp button ****
PumpInterface pump = MainApp.getConfigBuilder(); PumpInterface pump = MainApp.getConfigBuilder();
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
@ -513,8 +548,8 @@ public class OverviewFragment extends Fragment {
acceptTempLayout.setVisibility(View.GONE); acceptTempLayout.setVisibility(View.GONE);
} }
TempBasal activeTemp = pump.getTempBasal();
if (pump.isTempBasalInProgress()) { if (pump.isTempBasalInProgress()) {
TempBasal activeTemp = pump.getTempBasal();
cancelTempLayout.setVisibility(View.VISIBLE); cancelTempLayout.setVisibility(View.VISIBLE);
cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString()); cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString());
runningTempView.setVisibility(View.VISIBLE); runningTempView.setVisibility(View.VISIBLE);
@ -539,7 +574,7 @@ public class OverviewFragment extends Fragment {
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
profileswitch.executeProfileSwitch = true; profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch); newDialog.setOptions(profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
@ -578,10 +613,11 @@ public class OverviewFragment extends Fragment {
if (lastBG != null && bgView != null) { if (lastBG != null && bgView != null) {
bgView.setText(lastBG.valueToUnitsToString(profile.getUnits())); bgView.setText(lastBG.valueToUnitsToString(profile.getUnits()));
arrowView.setText(lastBG.directionToSymbol()); arrowView.setText(lastBG.directionToSymbol());
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (glucoseStatus != null){ if (glucoseStatus != null){
deltaView.setText("Δ " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units); deltaView.setText("Δ " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
avgdeltaView.setText("øΔ " + NSProfile.toUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units) + " " + units); avgdeltaView.setText("øΔ15m: " + NSProfile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) +
" øΔ40m: " + NSProfile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units));
} }
BgReading.units = profile.getUnits(); BgReading.units = profile.getUnits();
@ -602,16 +638,21 @@ public class OverviewFragment extends Fragment {
// iob // iob
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round(); IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
if (bolusIob == null) bolusIob = new IobTotal();
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round(); IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
if (basalIob == null) basalIob = new IobTotal();
String iobtext = getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" String iobtext = getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
+ getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
+ getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
iobView.setText(iobtext); iobView.setText(iobtext);
boolean showPrediction = showPredictionView.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class);
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
showPredictionView.setVisibility(View.VISIBLE);
} else {
showPredictionView.setVisibility(View.GONE);
}
// ****** GRAPH ******* // ****** GRAPH *******
// allign to hours // allign to hours
@ -622,9 +663,24 @@ public class OverviewFragment extends Fragment {
calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.MINUTE, 0);
calendar.add(Calendar.HOUR, 1); calendar.add(Calendar.HOUR, 1);
int hoursToFetch = 6; int hoursToFetch;
long toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding long toTime;
long fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; long fromTime;
long endTime;
if (showPrediction) {
int predHours = (int) (Math.ceil(((DetermineBasalResultAMA)finalLastRun.constraintsProcessed).getLatestPredictionsTime() - new Date().getTime()) / (60 * 60 * 1000));
predHours = Math.min(2, predHours);
predHours = Math.max(0, predHours);
hoursToFetch = (int) (6 - predHours);
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
endTime = toTime + predHours * 60 * 60 * 1000L;
} else {
hoursToFetch = 6;
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
endTime = toTime;
}
Double lowLine = SafeParse.stringToDouble(prefs.getString("low_mark", "0")); Double lowLine = SafeParse.stringToDouble(prefs.getString("low_mark", "0"));
Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0")); Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0"));
@ -637,12 +693,14 @@ public class OverviewFragment extends Fragment {
highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
} }
LineGraphSeries<DataPoint> basalsLineSeries = null;
BarGraphSeries<DataPoint> basalsSeries = null; BarGraphSeries<DataPoint> basalsSeries = null;
LineGraphSeries<DataPoint> seriesLow = null; LineGraphSeries<DataPoint> seriesLow = null;
LineGraphSeries<DataPoint> seriesHigh = null; LineGraphSeries<DataPoint> seriesHigh = null;
LineGraphSeries<DataPoint> seriesNow = null; LineGraphSeries<DataPoint> seriesNow = null;
PointsGraphSeries<BgReading> seriesInRage = null; PointsGraphSeries<BgReading> seriesInRage = null;
PointsGraphSeries<BgReading> seriesOutOfRange = null; PointsGraphSeries<BgReading> seriesOutOfRange = null;
PointsGraphSeries<BgReading> predSeries = null;
PointsWithLabelGraphSeries<Treatment> seriesTreatments = null; PointsWithLabelGraphSeries<Treatment> seriesTreatments = null;
// remove old data from graph // remove old data from graph
@ -651,11 +709,11 @@ public class OverviewFragment extends Fragment {
// **** HIGH and LOW targets graph **** // **** HIGH and LOW targets graph ****
DataPoint[] lowDataPoints = new DataPoint[]{ DataPoint[] lowDataPoints = new DataPoint[]{
new DataPoint(fromTime, lowLine), new DataPoint(fromTime, lowLine),
new DataPoint(toTime, lowLine) new DataPoint(endTime, lowLine)
}; };
DataPoint[] highDataPoints = new DataPoint[]{ DataPoint[] highDataPoints = new DataPoint[]{
new DataPoint(fromTime, highLine), new DataPoint(fromTime, highLine),
new DataPoint(toTime, highLine) new DataPoint(endTime, highLine)
}; };
bgGraph.addSeries(seriesLow = new LineGraphSeries<DataPoint>(lowDataPoints)); bgGraph.addSeries(seriesLow = new LineGraphSeries<DataPoint>(lowDataPoints));
seriesLow.setColor(Color.RED); seriesLow.setColor(Color.RED);
@ -672,19 +730,26 @@ public class OverviewFragment extends Fragment {
public boolean isTempBasal = false; public boolean isTempBasal = false;
} }
Double maxAllowedBasal = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
Double maxBasalValueFound = 0d; Double maxBasalValueFound = 0d;
long now = new Date().getTime(); long now = new Date().getTime();
if (pump.getPumpDescription().isTempBasalCapable) { if (pump.getPumpDescription().isTempBasalCapable) {
List<BarDataPoint> basalArray = new ArrayList<BarDataPoint>(); List<BarDataPoint> basalArray = new ArrayList<BarDataPoint>();
List<DataPoint> basalLineArray = new ArrayList<DataPoint>();
double lastBaseBasal = 0;
for (long time = fromTime; time < now; time += 5 * 60 * 1000L) { for (long time = fromTime; time < now; time += 5 * 60 * 1000L) {
TempBasal tb = MainApp.getConfigBuilder().getTempBasal(new Date(time)); TempBasal tb = MainApp.getConfigBuilder().getTempBasal(new Date(time));
double basebasal = profile.getBasal(NSProfile.secondsFromMidnight(new Date(time)));
Double basal = 0d; Double basal = 0d;
if (tb != null) if (tb != null)
basalArray.add(new BarDataPoint(time, basal = tb.tempBasalConvertedToAbsolute(new Date(time)), true)); basalArray.add(new BarDataPoint(time, basal = tb.tempBasalConvertedToAbsolute(new Date(time)), true));
else else {
basalArray.add(new BarDataPoint(time, basal = profile.getBasal(NSProfile.secondsFromMidnight(new Date(time))), false)); basalArray.add(new BarDataPoint(time, basal = basebasal, false));
}
if (basebasal != lastBaseBasal)
basalLineArray.add(new DataPoint(time, lastBaseBasal));
basalLineArray.add(new DataPoint(time, basebasal));
lastBaseBasal = basebasal;
maxBasalValueFound = Math.max(maxBasalValueFound, basal); maxBasalValueFound = Math.max(maxBasalValueFound, basal);
} }
BarDataPoint[] basal = new BarDataPoint[basalArray.size()]; BarDataPoint[] basal = new BarDataPoint[basalArray.size()];
@ -698,17 +763,23 @@ public class OverviewFragment extends Fragment {
else return Color.CYAN; else return Color.CYAN;
} }
}); });
DataPoint[] basalLine = new DataPoint[basalLineArray.size()];
basalLine = basalLineArray.toArray(basalLine);
bgGraph.addSeries(basalsLineSeries = new LineGraphSeries<DataPoint>(basalLine));
basalsLineSeries.setColor(Color.CYAN);
basalsLineSeries.setDrawDataPoints(false);
basalsLineSeries.setThickness(2);
} }
// set manual x bounds to have nice steps // set manual x bounds to have nice steps
bgGraph.getViewport().setMaxX(toTime); bgGraph.getViewport().setMaxX(endTime);
bgGraph.getViewport().setMinX(fromTime); bgGraph.getViewport().setMinX(fromTime);
bgGraph.getViewport().setXAxisBoundsManual(true); bgGraph.getViewport().setXAxisBoundsManual(true);
bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH"));
bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space
// **** BG graph **** // **** BG graph ****
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getDataFromTime(fromTime); List<BgReading> bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
List<BgReading> inRangeArray = new ArrayList<BgReading>(); List<BgReading> inRangeArray = new ArrayList<BgReading>();
List<BgReading> outOfRangeArray = new ArrayList<BgReading>(); List<BgReading> outOfRangeArray = new ArrayList<BgReading>();
@ -750,6 +821,19 @@ public class OverviewFragment extends Fragment {
seriesOutOfRange.setColor(Color.RED); seriesOutOfRange.setColor(Color.RED);
} }
if (showPrediction) {
DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed;
List<BgReading> predArray = amaResult.getPredictions();
BgReading[] pred = new BgReading[predArray.size()];
pred = predArray.toArray(pred);
if (pred.length > 0) {
bgGraph.addSeries(predSeries = new PointsGraphSeries<BgReading>(pred));
predSeries.setShape(PointsGraphSeries.Shape.POINT);
predSeries.setSize(4);
predSeries.setColor(Color.MAGENTA);
}
}
// **** NOW line **** // **** NOW line ****
DataPoint[] nowPoints = new DataPoint[]{ DataPoint[] nowPoints = new DataPoint[]{
new DataPoint(now, 0), new DataPoint(now, 0),
@ -762,8 +846,8 @@ public class OverviewFragment extends Fragment {
// custom paint to make a dotted line // custom paint to make a dotted line
Paint paint = new Paint(); Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE); paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1); paint.setStrokeWidth(2);
paint.setPathEffect(new DashPathEffect(new float[]{4, 20}, 0)); paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0));
paint.setColor(Color.WHITE); paint.setColor(Color.WHITE);
seriesNow.setCustomPaint(paint); seriesNow.setCustomPaint(paint);
@ -796,12 +880,11 @@ public class OverviewFragment extends Fragment {
// set second scale // set second scale
if (pump.getPumpDescription().isTempBasalCapable) { if (pump.getPumpDescription().isTempBasalCapable) {
bgGraph.getSecondScale().addSeries(basalsSeries); bgGraph.getSecondScale().addSeries(basalsSeries);
bgGraph.getSecondScale().addSeries(basalsLineSeries);
bgGraph.getSecondScale().setMinY(0); bgGraph.getSecondScale().setMinY(0);
bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d);
bgGraph.getGridLabelRenderer().setVerticalLabelsSecondScaleColor(MainApp.instance().getResources().getColor(R.color.background_material_dark)); // same color as backround = hide bgGraph.getGridLabelRenderer().setVerticalLabelsSecondScaleColor(MainApp.instance().getResources().getColor(R.color.background_material_dark)); // same color as backround = hide
} }
} }
//Notifications //Notifications

View file

@ -97,8 +97,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
if (profile == null) return absoluteRate; if (profile == null) return absoluteRate;
if (absoluteRate < 0) absoluteRate = 0d; if (absoluteRate < 0) absoluteRate = 0d;
Integer maxBasalMult = 4; Integer maxBasalMult = Constants.CURRENT_BASAL_SAFETY_MULTIPLIER;
Integer maxBasalFromDaily = 3; Integer maxBasalFromDaily = Constants.MAX_DAILY_SAFETY_MULTIPLIER;
// Check percentRate but absolute rate too, because we know real current basal in pump // Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate; Double origRate = absoluteRate;
if (absoluteRate > maxBasal) { if (absoluteRate > maxBasal) {
@ -136,8 +136,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
if (absoluteRate < 0) absoluteRate = 0d; if (absoluteRate < 0) absoluteRate = 0d;
Integer maxBasalMult = 4; Integer maxBasalMult = Constants.CURRENT_BASAL_SAFETY_MULTIPLIER;
Integer maxBasalFromDaily = 3; Integer maxBasalFromDaily = Constants.MAX_DAILY_SAFETY_MULTIPLIER;
// Check percentRate but absolute rate too, because we know real current basal in pump // Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate; Double origRate = absoluteRate;
if (absoluteRate > maxBasal) { if (absoluteRate > maxBasal) {

View file

@ -110,7 +110,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false);
profileswitch.executeProfileSwitch = true; profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch); newDialog.setOptions(profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");

View file

@ -21,16 +21,16 @@ 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.Services.Intents; import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
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.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
@ -213,16 +213,14 @@ public class SmsCommunicatorPlugin implements PluginBase {
} else if (lastBG != null) { } else if (lastBG != null) {
reply = MainApp.sResources.getString(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.sResources.getString(R.string.sms_minago), agoMin) + ", "; reply = MainApp.sResources.getString(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.sResources.getString(R.string.sms_minago), agoMin) + ", ";
} }
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (glucoseStatus != null) if (glucoseStatus != null)
reply += MainApp.sResources.getString(R.string.sms_delta) + " " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "; reply += MainApp.sResources.getString(R.string.sms_delta) + " " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", ";
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round(); IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
if (bolusIob == null) bolusIob = new IobTotal();
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round(); IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
if (basalIob == null) basalIob = new IobTotal();
reply += MainApp.sResources.getString(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" reply += MainApp.sResources.getString(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
+ MainApp.sResources.getString(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + MainApp.sResources.getString(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "

View file

@ -22,10 +22,10 @@ import java.util.List;
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.IobTotal;
import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;

View file

@ -5,9 +5,6 @@ import android.preference.PreferenceManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -28,7 +25,7 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
@ -95,44 +92,16 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
} }
private void initializeData() { private void initializeData() {
try { double dia = 3;
Dao<TempBasal, Long> dao = MainApp.getDbHelper().getDaoTempBasals(); if (MainApp.getConfigBuilder().getActiveProfile() != null && MainApp.getConfigBuilder().getActiveProfile().getProfile() != null)
/* dia = MainApp.getConfigBuilder().getActiveProfile().getProfile().getDia();
// **************** TESTING CREATE FAKE RECORD ***************** long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
TempBasal fake = new TempBasal(); tempBasals = MainApp.getDbHelper().getTempbasalsDataFromTime(fromMills, false, false);
fake.timeStart = new Date(new Date().getTime() - 45 * 40 * 1000); extendedBoluses = MainApp.getDbHelper().getTempbasalsDataFromTime(fromMills, false, true);
fake.timeEnd = new Date(new Date().getTime() - new Double(Math.random() * 45d * 40 * 1000).longValue());
fake.duration = 30;
fake.percent = 150;
fake.isAbsolute = false;
fake.isExtended = false;
dao.createOrUpdate(fake);
// **************** TESTING CREATE FAKE RECORD *****************
*/
QueryBuilder<TempBasal, Long> queryBuilder = dao.queryBuilder();
queryBuilder.orderBy("timeIndex", false);
Where where = queryBuilder.where();
where.eq("isExtended", false);
queryBuilder.limit(30L);
PreparedQuery<TempBasal> preparedQuery = queryBuilder.prepare();
tempBasals = dao.query(preparedQuery);
QueryBuilder<TempBasal, Long> queryBuilderExt = dao.queryBuilder(); // Update ended
queryBuilderExt.orderBy("timeIndex", false); checkForExpiredExtended();
Where whereExt = queryBuilderExt.where(); checkForExpiredTemps();
whereExt.eq("isExtended", true);
queryBuilderExt.limit(30L);
PreparedQuery<TempBasal> preparedQueryExt = queryBuilderExt.prepare();
extendedBoluses = dao.query(preparedQueryExt);
// Update ended
checkForExpiredExtended();
checkForExpiredTemps();
} catch (SQLException e) {
log.debug(e.getMessage(), e);
tempBasals = new ArrayList<TempBasal>();
extendedBoluses = new ArrayList<TempBasal>();
}
} }
public void checkForExpiredTemps() { public void checkForExpiredTemps() {
@ -197,13 +166,14 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
} }
@Override @Override
public void updateTotalIOB() { public IobTotal getCalculationToTime(long time) {
checkForExpired(tempBasals); checkForExpired(tempBasals);
checkForExpired(extendedBoluses); checkForExpired(extendedBoluses);
Date now = new Date(); Date now = new Date(time);
IobTotal total = new IobTotal(); IobTotal total = new IobTotal(time);
for (Integer pos = 0; pos < tempBasals.size(); pos++) { for (Integer pos = 0; pos < tempBasals.size(); pos++) {
TempBasal t = tempBasals.get(pos); TempBasal t = tempBasals.get(pos);
if (t.timeStart.getTime() > time) continue;
IobTotal calc = t.iobCalc(now); IobTotal calc = t.iobCalc(now);
total.plus(calc); total.plus(calc);
} }
@ -214,6 +184,13 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
total.plus(calc); total.plus(calc);
} }
} }
return total;
}
@Override
public void updateTotalIOB() {
IobTotal total = getCalculationToTime(new Date().getTime());
lastCalculationTimestamp = new Date().getTime(); lastCalculationTimestamp = new Date().getTime();
lastCalculation = total; lastCalculation = total;
} }
@ -237,6 +214,17 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
return null; return null;
} }
@Override
public long oldestDataAvaialable() {
long oldestTemp = new Date().getTime();
if (tempBasals.size() > 0)
oldestTemp = Math.min(oldestTemp, tempBasals.get(tempBasals.size() - 1).timeStart.getTime());
if (extendedBoluses.size() > 0)
oldestTemp = Math.min(oldestTemp, extendedBoluses.get(extendedBoluses.size() - 1).timeStart.getTime());
oldestTemp -= 15 * 60 * 1000L; // allow 15 min before
return oldestTemp;
}
List<TempBasal> getMergedList() { List<TempBasal> getMergedList() {
if (useExtendedBoluses) { if (useExtendedBoluses) {
List<TempBasal> merged = new ArrayList<TempBasal>(); List<TempBasal> merged = new ArrayList<TempBasal>();

View file

@ -0,0 +1,234 @@
package info.nightscout.androidaps.plugins.TempTargetRange;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Paint;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.j256.ormlite.dao.Dao;
import com.squareup.otto.Subscribe;
import java.sql.SQLException;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.ToastUtils;
/**
* Created by mike on 13/01/17.
*/
public class TempTargetRangeFragment extends Fragment implements View.OnClickListener, FragmentBase {
private static TempTargetRangePlugin tempTargetRangePlugin = new TempTargetRangePlugin();
public static TempTargetRangePlugin getPlugin() {
return tempTargetRangePlugin;
}
RecyclerView recyclerView;
LinearLayoutManager llm;
Button refreshFromNS;
Context context;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.TempTargetsViewHolder> {
List<TempTarget> tempTargetList;
RecyclerViewAdapter(List<TempTarget> TempTargetList) {
this.tempTargetList = TempTargetList;
}
@Override
public TempTargetsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.temptargetrange_item, viewGroup, false);
TempTargetsViewHolder TempTargetsViewHolder = new TempTargetsViewHolder(v);
return TempTargetsViewHolder;
}
@Override
public void onBindViewHolder(TempTargetsViewHolder holder, int position) {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
if (profile == null) return;
TempTarget tempTarget = tempTargetList.get(position);
holder.date.setText(DateUtil.dateAndTimeString(tempTarget.timeStart) + " - " + DateUtil.timeString(tempTargetList.get(position).getPlannedTimeEnd()));
holder.duration.setText(DecimalFormatter.to0Decimal(tempTarget.duration) + " min");
holder.low.setText(tempTarget.lowValueToUnitsToString(profile.getUnits()));
holder.high.setText(tempTarget.highValueToUnitsToString(profile.getUnits()));
holder.reason.setText(tempTarget.reason);
if (tempTarget.isInProgress())
holder.dateLinearLayout.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.colorInProgress));
else
holder.dateLinearLayout.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.cardColorBackground));
holder.remove.setTag(tempTarget);
}
@Override
public int getItemCount() {
return tempTargetList.size();
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public class TempTargetsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
TextView date;
TextView duration;
TextView low;
TextView high;
TextView reason;
TextView remove;
LinearLayout dateLinearLayout;
TempTargetsViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.temptargetrange_cardview);
date = (TextView) itemView.findViewById(R.id.temptargetrange_date);
duration = (TextView) itemView.findViewById(R.id.temptargetrange_duration);
low = (TextView) itemView.findViewById(R.id.temptargetrange_low);
high = (TextView) itemView.findViewById(R.id.temptargetrange_high);
reason = (TextView) itemView.findViewById(R.id.temptargetrange_reason);
remove = (TextView) itemView.findViewById(R.id.temptargetrange_remove);
remove.setOnClickListener(this);
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
dateLinearLayout = (LinearLayout) itemView.findViewById(R.id.temptargetrange_datelinearlayout);
}
@Override
public void onClick(View v) {
final TempTarget tempTarget = (TempTarget) v.getTag();
final Context finalContext = context;
switch (v.getId()) {
case R.id.temptargetrange_remove:
final String _id = tempTarget._id;
if (_id != null && !_id.equals("")) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + _id);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MainApp.getConfigBuilder().removeCareportalEntryFromNS(_id);
try {
Dao<TempTarget, Long> daoTempTargets = MainApp.getDbHelper().getDaoTempTargets();
daoTempTargets.delete(tempTarget);
MainApp.bus().post(new EventTempTargetRangeChange());
} catch (SQLException e) {
e.printStackTrace();
}
}
});
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);
builder.show();
}
break;
}
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.temptargetrange_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.temptargetrange_recyclerview);
recyclerView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(tempTargetRangePlugin.getList());
recyclerView.setAdapter(adapter);
refreshFromNS = (Button) view.findViewById(R.id.temptargetrange_refreshfromnightscout);
refreshFromNS.setOnClickListener(this);
context = getContext();
updateGUI();
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.temptargetrange_refreshfromnightscout:
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getContext());
boolean nsUploadOnly = SP.getBoolean("ns_upload_only", false);
if(nsUploadOnly){
ToastUtils.showToastInUiThread(getContext(),this.getContext().getString(R.string.ns_upload_only_enabled));
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage(this.getContext().getString(R.string.refreshtemptargetsfromnightscout));
builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MainApp.getDbHelper().resetTempTargets();
tempTargetRangePlugin.initializeData();
updateGUI();
Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
}
});
builder.setNegativeButton(this.getContext().getString(R.string.cancel), null);
builder.show();
}
break;
}
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Override
public void onResume() {
super.onResume();
MainApp.bus().register(this);
}
@Subscribe
public void onStatusEvent(final EventTempTargetRangeChange ev) {
updateGUI();
}
void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
recyclerView.swapAdapter(new RecyclerViewAdapter(tempTargetRangePlugin.getList()), false);
}
});
}
}

View file

@ -0,0 +1,100 @@
package info.nightscout.androidaps.plugins.TempTargetRange;
import android.support.annotation.Nullable;
import com.squareup.otto.Subscribe;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
/**
* Created by mike on 13/01/17.
*/
public class TempTargetRangePlugin implements PluginBase {
static boolean fragmentEnabled = true;
static boolean fragmentVisible = true;
private static List<TempTarget> tempTargets;
TempTargetRangePlugin() {
initializeData();
MainApp.bus().register(this);
}
@Override
public int getType() {
return PluginBase.GENERAL;
}
@Override
public String getFragmentClass() {
return TempTargetRangeFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.temptargetrange);
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == GENERAL && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) {
this.fragmentEnabled = fragmentEnabled;
}
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
}
public static boolean isEnabled() {
return fragmentEnabled;
}
@Subscribe
public void onStatusEvent(final EventTempTargetRangeChange ev) {
initializeData();
}
public void initializeData() {
long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * 24);
tempTargets = MainApp.getDbHelper().getTemptargetsDataFromTime(fromMills, false);
}
public List<TempTarget> getList() {
return tempTargets;
}
@Nullable
public TempTarget getTempTargetInProgress(long time) {
for (int i = tempTargets.size() - 1; i >= 0; i--) {
if (tempTargets.get(i).timeStart.getTime() > time) continue;
if (tempTargets.get(i).getPlannedTimeEnd().getTime() >= time) return tempTargets.get(i);
}
return null;
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.plugins.TempTargetRange.events;
/**
* Created by mike on 13.01.2017.
*/
public class EventTempTargetRangeChange {
}

View file

@ -157,7 +157,7 @@ public class TreatmentsFragment extends Fragment implements View.OnClickListener
} else { } else {
AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
builder.setTitle(this.getContext().getString(R.string.confirmation)); builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage(this.getContext().getString(R.string.refreshfromnightscout)); builder.setMessage(this.getContext().getString(R.string.refreshtreatmentsfromnightscout));
builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
MainApp.getDbHelper().resetTreatments(); MainApp.getDbHelper().resetTreatments();

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.Treatments;
import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -13,14 +14,17 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
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.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
/** /**
@ -83,17 +87,11 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
} }
public void initializeData() { public void initializeData() {
try { double dia = 3;
Dao<Treatment, Long> dao = MainApp.getDbHelper().getDaoTreatments(); if (MainApp.getConfigBuilder().getActiveProfile() != null && MainApp.getConfigBuilder().getActiveProfile().getProfile() != null)
QueryBuilder<Treatment, Long> queryBuilder = dao.queryBuilder(); dia = MainApp.getConfigBuilder().getActiveProfile().getProfile().getDia();
queryBuilder.orderBy("timeIndex", false); long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia));
queryBuilder.limit(30l); treatments = MainApp.getDbHelper().getTreatmentDataFromTime(fromMills, false);
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
treatments = dao.query(preparedQuery);
} catch (SQLException e) {
log.debug(e.getMessage(), e);
treatments = new ArrayList<Treatment>();
}
} }
/* /*
@ -111,57 +109,44 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
} }
@Override @Override
public void updateTotalIOB() { public IobTotal getCalculationToTime(long time) {
IobTotal total = new IobTotal(); IobTotal total = new IobTotal(time);
if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null) // app not initialized yet if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet
return; return total;
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
if (profile == null) { if (profile == null)
lastCalculation = total; return total;
return;
}
Double dia = profile.getDia(); Double dia = profile.getDia();
Date now = new Date(); Date now = new Date(time);
for (Integer pos = 0; pos < treatments.size(); pos++) { for (Integer pos = 0; pos < treatments.size(); pos++) {
Treatment t = treatments.get(pos); Treatment t = treatments.get(pos);
if (t.created_at.getTime() > time) continue;
Iob tIOB = t.iobCalc(now, dia); Iob tIOB = t.iobCalc(now, dia);
total.iob += tIOB.iobContrib; total.iob += tIOB.iobContrib;
total.activity += tIOB.activityContrib; total.activity += tIOB.activityContrib;
Iob bIOB = t.iobCalc(now, dia / 2); Iob bIOB = t.iobCalc(now, dia / Constants.BOLUSSNOOZE_DIA_ADVISOR);
total.bolussnooze += bIOB.iobContrib; total.bolussnooze += bIOB.iobContrib;
} }
return total;
}
@Override
public void updateTotalIOB() {
IobTotal total = getCalculationToTime(new Date().getTime());
lastCalculationTimestamp = new Date().getTime(); lastCalculationTimestamp = new Date().getTime();
lastCalculation = total; lastCalculation = total;
} }
public class MealData {
public double boluses = 0d;
public double carbs = 0d;
}
@Override @Override
public MealData getMealData() { public MealData getMealData() {
MealData result = new MealData(); MealData result = new MealData();
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null)
return result;
for (Treatment treatment : treatments) { for (Treatment treatment : treatments) {
long now = new Date().getTime(); result.addTreatment(treatment);
long dia_ago = now - (new Double(profile.getDia() * 60 * 60 * 1000l)).longValue();
long t = treatment.created_at.getTime();
if (t > dia_ago && t <= now) {
if (treatment.carbs >= 1) {
result.carbs += treatment.carbs;
}
if (treatment.insulin >= 0.1 && treatment.mealBolus) {
result.boluses += treatment.insulin;
}
}
} }
return result; return result;
} }

View file

@ -25,11 +25,11 @@ import java.util.List;
import info.nightscout.androidaps.Constants; 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.GlucoseStatus;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin; import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
@ -144,7 +144,7 @@ public class WatchUpdaterService extends WearableListenerService implements
BgReading lastBG = MainApp.getDbHelper().lastBg(); BgReading lastBG = MainApp.getDbHelper().lastBg();
if (lastBG != null) { if (lastBG != null) {
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); } if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); }
if (wear_integration) { if (wear_integration) {
@ -160,7 +160,7 @@ public class WatchUpdaterService extends WearableListenerService implements
} }
} }
private DataMap dataMapSingleBG(BgReading lastBG, DatabaseHelper.GlucoseStatus glucoseStatus) { private DataMap dataMapSingleBG(BgReading lastBG, GlucoseStatus glucoseStatus) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if(profile == null) return null; if(profile == null) return null;
@ -254,8 +254,8 @@ public class WatchUpdaterService extends WearableListenerService implements
if (last_bg == null) return; if (last_bg == null) return;
List<BgReading> graph_bgs = MainApp.getDbHelper().getDataFromTime(startTime); List<BgReading> graph_bgs = MainApp.getDbHelper().getBgreadingsDataFromTime(startTime, true);
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (!graph_bgs.isEmpty()) { if (!graph_bgs.isEmpty()) {
DataMap entries = dataMapSingleBG(last_bg, glucoseStatus); DataMap entries = dataMapSingleBG(last_bg, glucoseStatus);
@ -444,10 +444,8 @@ public class WatchUpdaterService extends WearableListenerService implements
//IOB //IOB
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round(); IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
if (bolusIob == null) bolusIob = new IobTotal();
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round(); IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
if (basalIob == null) basalIob = new IobTotal();
status += (shortString?"":(getString(R.string.treatments_iob_label_string) + " ")) + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "(" status += (shortString?"":(getString(R.string.treatments_iob_label_string) + " ")) + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "("
+ DecimalFormatter.to2Decimal(bolusIob.iob) + "|" + DecimalFormatter.to2Decimal(bolusIob.iob) + "|"
+ DecimalFormatter.to2Decimal(basalIob.basaliob) + ")"; + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")";

View file

@ -15,8 +15,8 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainActivity;
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.GlucoseStatus;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
@ -27,8 +27,7 @@ import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
@ -103,7 +102,7 @@ public class PersistentNotificationPlugin implements PluginBase{
BgReading lastBG = MainApp.getDbHelper().lastBg(); BgReading lastBG = MainApp.getDbHelper().lastBg();
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if(profile != null && lastBG != null) { if(profile != null && lastBG != null) {
line1 = lastBG.valueToUnitsToString(profile.getUnits()); line1 = lastBG.valueToUnitsToString(profile.getUnits());
@ -127,10 +126,8 @@ public class PersistentNotificationPlugin implements PluginBase{
//IOB //IOB
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round(); IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
if (bolusIob == null) bolusIob = new IobTotal();
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB(); MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round(); IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
if (basalIob == null) basalIob = new IobTotal();
String line2 = ctx.getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" String line2 = ctx.getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
+ ctx.getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + ctx.getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
+ ctx.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; + ctx.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";

View file

@ -26,4 +26,14 @@ public class DbLogger {
} else if (Config.logNSUpload) } else if (Config.logNSUpload)
log.debug("DBADD dbAdd " + q.size() + " receivers " + data); log.debug("DBADD dbAdd " + q.size() + " receivers " + data);
} }
public static void dbRemove(Intent intent, String data, Class sender) {
Logger log = LoggerFactory.getLogger(sender);
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0);
if (q.size() < 1) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.nsclientnotinstalled));
log.error("DBREMOVE No receivers");
} else if (Config.logNSUpload)
log.debug("DBREMOVE dbRemove " + q.size() + " receivers " + data);
}
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
{
"bg": 148,
"temp": "absolute",
"snoozeBG": 17,
"recieved": true,
"predBGs": {
"IOB": [
148,
128,
109,
91,
75,
59,
45,
39,
39,
39,
39,
39,
39
]
},
"rate": 0.0,
"reason": "COB: 0, Dev: -64, BGI: -8.24, ISF: 21, Target: 81; Eventual BG -34 < 81, setting -11.1U/hr",
"COB": 0,
"eventualBG": -34,
"timestamp": "2017-01-04T16:37:56.113148",
"duration": 30,
"tick": -21,
"IOB": 5.521
}

View file

@ -0,0 +1 @@
{"temp":"absolute","bg":148,"tick":-21,"eventualBG":-28,"snoozeBG":16,"predBGs":{"IOB":[148,128,109,92,75,60,46,39,39,39,39,39,39]},"COB":0,"IOB":5.248,"reason":"COB: 0, Dev: -64, BGI: -8.2, ISF: 21, Target: 81; Eventual BG -28 < 81, setting -11.3U/hr, but 28m left and 0 ~ req 0U/hr: no action required"}

View file

@ -0,0 +1,4 @@
{
"status": "normal",
"voltage": 1.45
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
"2017-01-04T16:40:31+01:00"

View file

@ -0,0 +1 @@
"2017-01-04T16:40:31"

View file

@ -0,0 +1,4 @@
{
"battery": 52,
"batteryVoltage": 3701
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"carbs":0,"boluses":8,"mealCOB":0}

View file

@ -0,0 +1,131 @@
{
"scanDetails": [
[
"868.300",
0,
-99
],
[
"868.312",
0,
-99
],
[
"868.324",
0,
-99
],
[
"868.336",
0,
-99
],
[
"868.348",
0,
-99
],
[
"868.360",
0,
-99
],
[
"868.372",
4,
-91
],
[
"868.384",
5,
-81
],
[
"868.396",
5,
-78
],
[
"868.408",
5,
-77
],
[
"868.420",
5,
-76
],
[
"868.432",
5,
-76
],
[
"868.444",
5,
-76
],
[
"868.456",
5,
-76
],
[
"868.468",
5,
-75
],
[
"868.480",
5,
-76
],
[
"868.492",
5,
-76
],
[
"868.504",
5,
-77
],
[
"868.516",
5,
-80
],
[
"868.528",
5,
-86
],
[
"868.540",
0,
-99
],
[
"868.552",
0,
-99
],
[
"868.564",
0,
-99
],
[
"868.576",
0,
-99
],
[
"868.588",
0,
-99
]
],
"setFreq": 868.468,
"usedDefault": false
}

View file

@ -0,0 +1,936 @@
[
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:37:57 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:37:57+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "3965104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:37:57 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:37:57+01:00",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "3965104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:28:28 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:28:28+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1c5c104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:28:28 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:28:28+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "1c5c104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:21:31 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:21:31+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1f55104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:21:31 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:21:31+01:00",
"_body": "00",
"_head": "337c",
"rate": 3.1,
"_date": "1f55104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:15:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:15:29+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1d4f104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:15:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:15:29+01:00",
"_body": "00",
"_head": "3362",
"rate": 2.45,
"_date": "1d4f104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:08:41 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:08:41+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2948104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:08:41 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:08:41+01:00",
"_body": "00",
"_head": "334e",
"rate": 1.95,
"_date": "2948104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:06:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:06:50+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "3246104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:06:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:06:50+01:00",
"_body": "00",
"_head": "3332",
"rate": 1.25,
"_date": "3246104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:02:03 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:02:03+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "0342104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:02:03 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:02:03+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "0342104411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:01:28 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:01:28+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1c41104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:01:28 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:01:28+01:00",
"_body": "00",
"_head": "3396",
"rate": 3.75,
"_date": "1c41104411"
},
{
"_type": "Bolus",
"_description": "Bolus 2017-01-04T15:58:37 head[4], body[0] op[0x01]",
"timestamp": "2017-01-04T15:58:37+01:00",
"_body": "",
"programmed": 2.0,
"_head": "01141400",
"amount": 2.0,
"duration": 0,
"type": "normal",
"_date": "257a4f0411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:55:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:55:29+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1d770f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:55:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:55:29+01:00",
"_body": "00",
"_head": "332d",
"rate": 1.125,
"_date": "1d770f4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:46:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:46:50+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "326e0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:46:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:46:50+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "326e0f4411"
},
{
"_type": "Bolus",
"_description": "Bolus 2017-01-04T15:44:07 head[4], body[0] op[0x01]",
"timestamp": "2017-01-04T15:44:07+01:00",
"_body": "",
"programmed": 2.0,
"_head": "01141400",
"amount": 2.0,
"duration": 0,
"type": "normal",
"_date": "076c4f0411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:43:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:43:50+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "326b0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:43:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:43:50+01:00",
"_body": "00",
"_head": "3341",
"rate": 1.625,
"_date": "326b0f4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:41:22 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:41:22+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "16690f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:41:22 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:41:22+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "16690f4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:28:24 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:28:24+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "185c0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:28:24 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:28:24+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "185c0f4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:22:58 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:22:58+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "3a560f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:22:58 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:22:58+01:00",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "3a560f4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T15:13:01 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:13:01+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "014d0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:13:01 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:13:01+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "014d0f4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:50:21 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:50:21+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "15720e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:50:21 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:50:21+01:00",
"_body": "00",
"_head": "33fb",
"rate": 6.275,
"_date": "15720e4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:38:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:38:50+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "32660e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:38:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:38:50+01:00",
"_body": "00",
"_head": "33e7",
"rate": 5.775,
"_date": "32660e4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:34:03 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:34:03+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "03620e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:34:03 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:34:03+01:00",
"_body": "00",
"_head": "3344",
"rate": 1.7,
"_date": "03620e4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:33:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:33:29+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1d610e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:33:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:33:29+01:00",
"_body": "00",
"_head": "3392",
"rate": 3.65,
"_date": "1d610e4411"
},
{
"_type": "Bolus",
"_description": "Bolus 2017-01-04T14:32:05 head[4], body[0] op[0x01]",
"timestamp": "2017-01-04T14:32:05+01:00",
"_body": "",
"programmed": 1.0,
"_head": "010a0a00",
"amount": 1.0,
"duration": 0,
"type": "normal",
"_date": "05604e0411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:26:30 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:26:30+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1e5a0e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:26:30 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:26:30+01:00",
"_body": "00",
"_head": "3320",
"rate": 0.8,
"_date": "1e5a0e4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:25:47 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:25:47+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2f590e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:25:47 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:25:47+01:00",
"_body": "00",
"_head": "3378",
"rate": 3.0,
"_date": "2f590e4411"
},
{
"_type": "Bolus",
"_description": "Bolus 2017-01-04T14:22:59 head[4], body[0] op[0x01]",
"timestamp": "2017-01-04T14:22:59+01:00",
"_body": "",
"programmed": 2.0,
"_head": "01141400",
"amount": 2.0,
"duration": 0,
"type": "normal",
"_date": "3b564e0411"
},
{
"_type": "Prime",
"_description": "Prime 2017-01-04T14:18:15 head[5], body[0] op[0x03]",
"timestamp": "2017-01-04T14:18:15+01:00",
"_body": "",
"_head": "0300000027",
"amount": 3.9,
"fixed": 0.0,
"type": "manual",
"_date": "0f522e0411"
},
{
"_type": "Rewind",
"_description": "Rewind 2017-01-04T14:18:03 head[2], body[0] op[0x21]",
"timestamp": "2017-01-04T14:18:03+01:00",
"_body": "",
"_head": "2100",
"_date": "03520e0411"
},
{
"_type": "Prime",
"_description": "Prime 2017-01-04T14:17:15 head[5], body[0] op[0x03]",
"timestamp": "2017-01-04T14:17:15+01:00",
"_body": "",
"_head": "03000a000a",
"amount": 1.0,
"fixed": 1.0,
"type": "fixed",
"_date": "0f510e0411"
},
{
"_type": "Prime",
"_description": "Prime 2017-01-04T14:14:56 head[5], body[0] op[0x03]",
"timestamp": "2017-01-04T14:14:56+01:00",
"_body": "",
"_head": "0300190019",
"amount": 2.5,
"fixed": 2.5,
"type": "fixed",
"_date": "384e0e0411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:14:32 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:14:32+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "204e0e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:14:32 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:14:32+01:00",
"_body": "00",
"_head": "3346",
"rate": 1.75,
"_date": "204e0e4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T14:09:45 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:09:45+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2d490e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:09:45 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:09:45+01:00",
"_body": "00",
"_head": "3337",
"rate": 1.375,
"_date": "2d490e4411"
},
{
"_type": "ClearAlarm",
"_description": "ClearAlarm 2017-01-04T14:04:16 head[2], body[0] op[0x0c]",
"timestamp": "2017-01-04T14:04:16+01:00",
"_body": "",
"_head": "0c04",
"_date": "10440e0411"
},
{
"_type": "AlarmPump",
"_description": "AlarmPump 2017-01-04T14:04:05 head[4], body[0] op[0x06]",
"timestamp": "2017-01-04T14:04:05+01:00",
"_body": "",
"_head": "06040bff",
"_date": "05444e4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:57:38 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:57:38+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "26790d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:57:38 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:57:38+01:00",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "26790d4411"
},
{
"_type": "Bolus",
"_description": "Bolus 2017-01-04T13:53:05 head[4], body[0] op[0x01]",
"timestamp": "2017-01-04T13:53:05+01:00",
"_body": "",
"programmed": 1.0,
"_head": "010a0a00",
"amount": 1.0,
"duration": 0,
"type": "normal",
"_date": "05754d0411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:47:51 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:47:51+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "336f0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:47:51 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:47:51+01:00",
"_body": "00",
"_head": "3368",
"rate": 2.6,
"_date": "336f0d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:43:53 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:43:53+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "356b0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:43:53 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:43:53+01:00",
"_body": "00",
"_head": "3355",
"rate": 2.125,
"_date": "356b0d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:40:04 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:40:04+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "04680d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:40:04 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:40:04+01:00",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "04680d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:27:46 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:27:46+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2e5b0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:27:46 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:27:46+01:00",
"_body": "00",
"_head": "3348",
"rate": 1.8,
"_date": "2e5b0d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:27:00 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:27:00+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "005b0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:27:00 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:27:00+01:00",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "005b0d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:20:49 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:20:49+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "31540d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:20:49 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:20:49+01:00",
"_body": "00",
"_head": "332d",
"rate": 1.125,
"_date": "31540d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:15:40 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:15:40+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "284f0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:15:40 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:15:40+01:00",
"_body": "00",
"_head": "3373",
"rate": 2.875,
"_date": "284f0d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:15:31 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:15:31+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1f4f0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:15:31 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:15:31+01:00",
"_body": "00",
"_head": "3373",
"rate": 2.875,
"_date": "1f4f0d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:08:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:08:29+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1d480d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:08:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:08:29+01:00",
"_body": "00",
"_head": "332c",
"rate": 1.1,
"_date": "1d480d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T13:03:28 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:03:28+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1c430d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:03:28 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:03:28+01:00",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "1c430d4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:57:44 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:57:44+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2c790c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:57:44 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:57:44+01:00",
"_body": "00",
"_head": "332a",
"rate": 1.05,
"_date": "2c790c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:47:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:47:29+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1d6f0c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:47:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:47:29+01:00",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "1d6f0c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:35:30 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:35:30+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1e630c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:35:30 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:35:30+01:00",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "1e630c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:23:47 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:23:47+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2f570c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:23:47 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:23:47+01:00",
"_body": "00",
"_head": "33b5",
"rate": 4.525,
"_date": "2f570c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:18:48 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:18:48+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "30520c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:18:48 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:18:48+01:00",
"_body": "00",
"_head": "334a",
"rate": 1.85,
"_date": "30520c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:13:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:13:29+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "1d4d0c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:13:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:13:29+01:00",
"_body": "00",
"_head": "3337",
"rate": 1.375,
"_date": "1d4d0c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T12:08:07 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:08:07+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "07480c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:08:07 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:08:07+01:00",
"_body": "00",
"_head": "3324",
"rate": 0.9,
"_date": "07480c4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T11:55:46 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T11:55:46+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2e770b4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T11:55:46 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T11:55:46+01:00",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "2e770b4411"
},
{
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T11:42:44 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T11:42:44+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "2c6a0b4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T11:42:44 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T11:42:44+01:00",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "2c6a0b4411"
}
]

View file

@ -0,0 +1,936 @@
[
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:37:57 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:37:57",
"_body": "",
"_head": "1601",
"_date": "3965104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:37:57 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:37:57",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "3965104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:28:28 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:28:28",
"_body": "",
"_head": "1601",
"_date": "1c5c104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:28:28 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:28:28",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "1c5c104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:21:31 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:21:31",
"_body": "",
"_head": "1601",
"_date": "1f55104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:21:31 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:21:31",
"_body": "00",
"_head": "337c",
"rate": 3.1,
"_date": "1f55104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:15:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:15:29",
"_body": "",
"_head": "1601",
"_date": "1d4f104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:15:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:15:29",
"_body": "00",
"_head": "3362",
"rate": 2.45,
"_date": "1d4f104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:08:41 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:08:41",
"_body": "",
"_head": "1601",
"_date": "2948104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:08:41 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:08:41",
"_body": "00",
"_head": "334e",
"rate": 1.95,
"_date": "2948104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:06:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:06:50",
"_body": "",
"_head": "1601",
"_date": "3246104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:06:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:06:50",
"_body": "00",
"_head": "3332",
"rate": 1.25,
"_date": "3246104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:02:03 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:02:03",
"_body": "",
"_head": "1601",
"_date": "0342104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:02:03 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:02:03",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "0342104411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T16:01:28 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:01:28",
"_body": "",
"_head": "1601",
"_date": "1c41104411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:01:28 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:01:28",
"_body": "00",
"_head": "3396",
"rate": 3.75,
"_date": "1c41104411"
},
{
"programmed": 2.0,
"_type": "Bolus",
"type": "normal",
"_description": "Bolus 2017-01-04T15:58:37 head[4], body[0] op[0x01]",
"duration": 0,
"timestamp": "2017-01-04T15:58:37",
"_body": "",
"_head": "01141400",
"amount": 2.0,
"_date": "257a4f0411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:55:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:55:29",
"_body": "",
"_head": "1601",
"_date": "1d770f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:55:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:55:29",
"_body": "00",
"_head": "332d",
"rate": 1.125,
"_date": "1d770f4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:46:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:46:50",
"_body": "",
"_head": "1601",
"_date": "326e0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:46:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:46:50",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "326e0f4411"
},
{
"programmed": 2.0,
"_type": "Bolus",
"type": "normal",
"_description": "Bolus 2017-01-04T15:44:07 head[4], body[0] op[0x01]",
"duration": 0,
"timestamp": "2017-01-04T15:44:07",
"_body": "",
"_head": "01141400",
"amount": 2.0,
"_date": "076c4f0411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:43:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:43:50",
"_body": "",
"_head": "1601",
"_date": "326b0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:43:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:43:50",
"_body": "00",
"_head": "3341",
"rate": 1.625,
"_date": "326b0f4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:41:22 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:41:22",
"_body": "",
"_head": "1601",
"_date": "16690f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:41:22 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:41:22",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "16690f4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:28:24 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:28:24",
"_body": "",
"_head": "1601",
"_date": "185c0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:28:24 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:28:24",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "185c0f4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:22:58 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:22:58",
"_body": "",
"_head": "1601",
"_date": "3a560f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:22:58 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:22:58",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "3a560f4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T15:13:01 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T15:13:01",
"_body": "",
"_head": "1601",
"_date": "014d0f4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T15:13:01 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T15:13:01",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "014d0f4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:50:21 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:50:21",
"_body": "",
"_head": "1601",
"_date": "15720e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:50:21 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:50:21",
"_body": "00",
"_head": "33fb",
"rate": 6.275,
"_date": "15720e4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:38:50 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:38:50",
"_body": "",
"_head": "1601",
"_date": "32660e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:38:50 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:38:50",
"_body": "00",
"_head": "33e7",
"rate": 5.775,
"_date": "32660e4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:34:03 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:34:03",
"_body": "",
"_head": "1601",
"_date": "03620e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:34:03 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:34:03",
"_body": "00",
"_head": "3344",
"rate": 1.7,
"_date": "03620e4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:33:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:33:29",
"_body": "",
"_head": "1601",
"_date": "1d610e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:33:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:33:29",
"_body": "00",
"_head": "3392",
"rate": 3.65,
"_date": "1d610e4411"
},
{
"programmed": 1.0,
"_type": "Bolus",
"type": "normal",
"_description": "Bolus 2017-01-04T14:32:05 head[4], body[0] op[0x01]",
"duration": 0,
"timestamp": "2017-01-04T14:32:05",
"_body": "",
"_head": "010a0a00",
"amount": 1.0,
"_date": "05604e0411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:26:30 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:26:30",
"_body": "",
"_head": "1601",
"_date": "1e5a0e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:26:30 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:26:30",
"_body": "00",
"_head": "3320",
"rate": 0.8,
"_date": "1e5a0e4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:25:47 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:25:47",
"_body": "",
"_head": "1601",
"_date": "2f590e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:25:47 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:25:47",
"_body": "00",
"_head": "3378",
"rate": 3.0,
"_date": "2f590e4411"
},
{
"programmed": 2.0,
"_type": "Bolus",
"type": "normal",
"_description": "Bolus 2017-01-04T14:22:59 head[4], body[0] op[0x01]",
"duration": 0,
"timestamp": "2017-01-04T14:22:59",
"_body": "",
"_head": "01141400",
"amount": 2.0,
"_date": "3b564e0411"
},
{
"_type": "Prime",
"type": "manual",
"_description": "Prime 2017-01-04T14:18:15 head[5], body[0] op[0x03]",
"timestamp": "2017-01-04T14:18:15",
"_body": "",
"fixed": 0.0,
"_head": "0300000027",
"amount": 3.9,
"_date": "0f522e0411"
},
{
"_type": "Rewind",
"_description": "Rewind 2017-01-04T14:18:03 head[2], body[0] op[0x21]",
"timestamp": "2017-01-04T14:18:03",
"_body": "",
"_head": "2100",
"_date": "03520e0411"
},
{
"_type": "Prime",
"type": "fixed",
"_description": "Prime 2017-01-04T14:17:15 head[5], body[0] op[0x03]",
"timestamp": "2017-01-04T14:17:15",
"_body": "",
"fixed": 1.0,
"_head": "03000a000a",
"amount": 1.0,
"_date": "0f510e0411"
},
{
"_type": "Prime",
"type": "fixed",
"_description": "Prime 2017-01-04T14:14:56 head[5], body[0] op[0x03]",
"timestamp": "2017-01-04T14:14:56",
"_body": "",
"fixed": 2.5,
"_head": "0300190019",
"amount": 2.5,
"_date": "384e0e0411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:14:32 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:14:32",
"_body": "",
"_head": "1601",
"_date": "204e0e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:14:32 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:14:32",
"_body": "00",
"_head": "3346",
"rate": 1.75,
"_date": "204e0e4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T14:09:45 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T14:09:45",
"_body": "",
"_head": "1601",
"_date": "2d490e4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T14:09:45 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T14:09:45",
"_body": "00",
"_head": "3337",
"rate": 1.375,
"_date": "2d490e4411"
},
{
"_type": "ClearAlarm",
"_description": "ClearAlarm 2017-01-04T14:04:16 head[2], body[0] op[0x0c]",
"timestamp": "2017-01-04T14:04:16",
"_body": "",
"_head": "0c04",
"_date": "10440e0411"
},
{
"_type": "AlarmPump",
"_description": "AlarmPump 2017-01-04T14:04:05 head[4], body[0] op[0x06]",
"timestamp": "2017-01-04T14:04:05",
"_body": "",
"_head": "06040bff",
"_date": "05444e4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:57:38 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:57:38",
"_body": "",
"_head": "1601",
"_date": "26790d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:57:38 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:57:38",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "26790d4411"
},
{
"programmed": 1.0,
"_type": "Bolus",
"type": "normal",
"_description": "Bolus 2017-01-04T13:53:05 head[4], body[0] op[0x01]",
"duration": 0,
"timestamp": "2017-01-04T13:53:05",
"_body": "",
"_head": "010a0a00",
"amount": 1.0,
"_date": "05754d0411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:47:51 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:47:51",
"_body": "",
"_head": "1601",
"_date": "336f0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:47:51 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:47:51",
"_body": "00",
"_head": "3368",
"rate": 2.6,
"_date": "336f0d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:43:53 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:43:53",
"_body": "",
"_head": "1601",
"_date": "356b0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:43:53 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:43:53",
"_body": "00",
"_head": "3355",
"rate": 2.125,
"_date": "356b0d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:40:04 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:40:04",
"_body": "",
"_head": "1601",
"_date": "04680d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:40:04 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:40:04",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "04680d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:27:46 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:27:46",
"_body": "",
"_head": "1601",
"_date": "2e5b0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:27:46 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:27:46",
"_body": "00",
"_head": "3348",
"rate": 1.8,
"_date": "2e5b0d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:27:00 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:27:00",
"_body": "",
"_head": "1601",
"_date": "005b0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:27:00 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:27:00",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "005b0d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:20:49 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:20:49",
"_body": "",
"_head": "1601",
"_date": "31540d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:20:49 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:20:49",
"_body": "00",
"_head": "332d",
"rate": 1.125,
"_date": "31540d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:15:40 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:15:40",
"_body": "",
"_head": "1601",
"_date": "284f0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:15:40 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:15:40",
"_body": "00",
"_head": "3373",
"rate": 2.875,
"_date": "284f0d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:15:31 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:15:31",
"_body": "",
"_head": "1601",
"_date": "1f4f0d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:15:31 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:15:31",
"_body": "00",
"_head": "3373",
"rate": 2.875,
"_date": "1f4f0d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:08:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:08:29",
"_body": "",
"_head": "1601",
"_date": "1d480d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:08:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:08:29",
"_body": "00",
"_head": "332c",
"rate": 1.1,
"_date": "1d480d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T13:03:28 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T13:03:28",
"_body": "",
"_head": "1601",
"_date": "1c430d4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T13:03:28 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T13:03:28",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "1c430d4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:57:44 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:57:44",
"_body": "",
"_head": "1601",
"_date": "2c790c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:57:44 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:57:44",
"_body": "00",
"_head": "332a",
"rate": 1.05,
"_date": "2c790c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:47:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:47:29",
"_body": "",
"_head": "1601",
"_date": "1d6f0c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:47:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:47:29",
"_body": "00",
"_head": "331e",
"rate": 0.75,
"_date": "1d6f0c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:35:30 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:35:30",
"_body": "",
"_head": "1601",
"_date": "1e630c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:35:30 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:35:30",
"_body": "00",
"_head": "3322",
"rate": 0.85,
"_date": "1e630c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:23:47 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:23:47",
"_body": "",
"_head": "1601",
"_date": "2f570c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:23:47 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:23:47",
"_body": "00",
"_head": "33b5",
"rate": 4.525,
"_date": "2f570c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:18:48 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:18:48",
"_body": "",
"_head": "1601",
"_date": "30520c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:18:48 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:18:48",
"_body": "00",
"_head": "334a",
"rate": 1.85,
"_date": "30520c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:13:29 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:13:29",
"_body": "",
"_head": "1601",
"_date": "1d4d0c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:13:29 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:13:29",
"_body": "00",
"_head": "3337",
"rate": 1.375,
"_date": "1d4d0c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T12:08:07 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T12:08:07",
"_body": "",
"_head": "1601",
"_date": "07480c4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T12:08:07 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T12:08:07",
"_body": "00",
"_head": "3324",
"rate": 0.9,
"_date": "07480c4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T11:55:46 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T11:55:46",
"_body": "",
"_head": "1601",
"_date": "2e770b4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T11:55:46 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T11:55:46",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "2e770b4411"
},
{
"_type": "TempBasalDuration",
"duration (min)": 30,
"_description": "TempBasalDuration 2017-01-04T11:42:44 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T11:42:44",
"_body": "",
"_head": "1601",
"_date": "2c6a0b4411"
},
{
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T11:42:44 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T11:42:44",
"_body": "00",
"_head": "3300",
"rate": 0.0,
"_date": "2c6a0b4411"
}
]

View file

@ -0,0 +1 @@
120.5

View file

@ -0,0 +1,5 @@
{
"status": "normal",
"bolusing": false,
"suspended": false
}

View file

@ -0,0 +1,5 @@
{
"duration": 28,
"rate": 0.0,
"temp": "absolute"
}

View file

@ -0,0 +1 @@
{"ratio":1.4}

View file

@ -0,0 +1,140 @@
[
{
"i": 0,
"start": "00:00:00",
"rate": 1.0,
"minutes": 0
},
{
"i": 1,
"start": "01:00:00",
"rate": 0.9,
"minutes": 60
},
{
"i": 2,
"start": "02:00:00",
"rate": 0.8,
"minutes": 120
},
{
"i": 3,
"start": "03:00:00",
"rate": 0.8,
"minutes": 180
},
{
"i": 4,
"start": "04:00:00",
"rate": 1.3,
"minutes": 240
},
{
"i": 5,
"start": "05:00:00",
"rate": 1.4000000000000001,
"minutes": 300
},
{
"i": 6,
"start": "06:00:00",
"rate": 1.8,
"minutes": 360
},
{
"i": 7,
"start": "07:00:00",
"rate": 1.8,
"minutes": 420
},
{
"i": 8,
"start": "08:00:00",
"rate": 1.8,
"minutes": 480
},
{
"i": 9,
"start": "09:00:00",
"rate": 1.5,
"minutes": 540
},
{
"i": 10,
"start": "10:00:00",
"rate": 1.0,
"minutes": 600
},
{
"i": 11,
"start": "11:00:00",
"rate": 0.9,
"minutes": 660
},
{
"i": 12,
"start": "12:00:00",
"rate": 0.6000000000000001,
"minutes": 720
},
{
"i": 13,
"start": "13:00:00",
"rate": 0.6000000000000001,
"minutes": 780
},
{
"i": 14,
"start": "14:00:00",
"rate": 0.6000000000000001,
"minutes": 840
},
{
"i": 15,
"start": "15:00:00",
"rate": 0.6000000000000001,
"minutes": 900
},
{
"i": 16,
"start": "17:00:00",
"rate": 0.6000000000000001,
"minutes": 1020
},
{
"i": 17,
"start": "18:00:00",
"rate": 0.6000000000000001,
"minutes": 1080
},
{
"i": 18,
"start": "19:00:00",
"rate": 0.6000000000000001,
"minutes": 1140
},
{
"i": 19,
"start": "20:00:00",
"rate": 0.6000000000000001,
"minutes": 1200
},
{
"i": 20,
"start": "21:00:00",
"rate": 0.6000000000000001,
"minutes": 1260
},
{
"i": 21,
"start": "22:00:00",
"rate": 0.6000000000000001,
"minutes": 1320
},
{
"i": 22,
"start": "23:00:00",
"rate": 0.6000000000000001,
"minutes": 1380
}
]

View file

@ -0,0 +1,16 @@
{
"units": "mg/dL",
"raw": "0x01 0x00 0x5a 0x5a 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00",
"user_preferred_units": "mg/dL",
"targets": [
{
"i": 0,
"high": 90,
"start": "00:00:00",
"low": 90,
"offset": 0,
"x": 0
}
],
"first": 1
}

View file

@ -0,0 +1,15 @@
{
"units": "mg/dL",
"raw": "0x01 0x00 0x5a 0x5a 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00",
"targets": [
{
"high": 90,
"start": "00:00:00",
"low": 90,
"offset": 0,
"i": 0,
"x": 0
}
],
"first": 1
}

View file

@ -0,0 +1,31 @@
{
"units": "grams",
"raw": "0x01 0x00 0x09 0x0b 0x07 0x12 0x09 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00",
"first": 1,
"schedule": [
{
"start": "00:00:00",
"r": 9,
"ratio": 9,
"offset": 0,
"i": 0,
"x": 0
},
{
"start": "05:30:00",
"r": 7,
"ratio": 7,
"offset": 330,
"i": 11,
"x": 1
},
{
"start": "09:00:00",
"r": 9,
"ratio": 9,
"offset": 540,
"i": 18,
"x": 2
}
]
}

View file

@ -0,0 +1,28 @@
{
"units": "mg/dL",
"user_preferred_units": "mg/dL",
"sensitivities": [
{
"i": 0,
"start": "00:00:00",
"sensitivity": 35,
"x": 0,
"offset": 0
},
{
"i": 8,
"start": "04:00:00",
"sensitivity": 30,
"x": 1,
"offset": 240
},
{
"i": 20,
"start": "10:00:00",
"sensitivity": 30,
"x": 2,
"offset": 600
}
],
"first": 1
}

View file

@ -0,0 +1,27 @@
{
"units": "mg/dL",
"sensitivities": [
{
"i": 0,
"start": "00:00:00",
"sensitivity": 35,
"offset": 0,
"x": 0
},
{
"i": 8,
"start": "04:00:00",
"sensitivity": 30,
"offset": 240,
"x": 1
},
{
"i": 20,
"start": "10:00:00",
"sensitivity": 30,
"offset": 600,
"x": 2
}
],
"first": 1
}

View file

@ -0,0 +1 @@
"522"

View file

@ -0,0 +1 @@
{"max_iob":15,"max_daily_safety_multiplier":9,"current_basal_safety_multiplier":12,"autosens_max":1.4,"autosens_min":0.6,"autosens_adjust_targets":true,"override_high_target_with_low":false,"skip_neutral_temps":false,"bolussnooze_dia_divisor":2,"min_5m_carbimpact":3,"carbratio_adjustmentratio":1,"dia":3,"model":"522","current_basal":0.6,"basalprofile":[{"i":0,"start":"00:00:00","rate":1,"minutes":0},{"i":1,"start":"01:00:00","rate":0.9,"minutes":60},{"i":2,"start":"02:00:00","rate":0.8,"minutes":120},{"i":3,"start":"03:00:00","rate":0.8,"minutes":180},{"i":4,"start":"04:00:00","rate":1.3,"minutes":240},{"i":5,"start":"05:00:00","rate":1.4000000000000001,"minutes":300},{"i":6,"start":"06:00:00","rate":1.8,"minutes":360},{"i":7,"start":"07:00:00","rate":1.8,"minutes":420},{"i":8,"start":"08:00:00","rate":1.8,"minutes":480},{"i":9,"start":"09:00:00","rate":1.5,"minutes":540},{"i":10,"start":"10:00:00","rate":1,"minutes":600},{"i":11,"start":"11:00:00","rate":0.9,"minutes":660},{"i":12,"start":"12:00:00","rate":0.6000000000000001,"minutes":720},{"i":13,"start":"13:00:00","rate":0.6000000000000001,"minutes":780},{"i":14,"start":"14:00:00","rate":0.6000000000000001,"minutes":840},{"i":15,"start":"15:00:00","rate":0.6000000000000001,"minutes":900},{"i":16,"start":"17:00:00","rate":0.6000000000000001,"minutes":1020},{"i":17,"start":"18:00:00","rate":0.6000000000000001,"minutes":1080},{"i":18,"start":"19:00:00","rate":0.6000000000000001,"minutes":1140},{"i":19,"start":"20:00:00","rate":0.6000000000000001,"minutes":1200},{"i":20,"start":"21:00:00","rate":0.6000000000000001,"minutes":1260},{"i":21,"start":"22:00:00","rate":0.6000000000000001,"minutes":1320},{"i":22,"start":"23:00:00","rate":0.6000000000000001,"minutes":1380}],"max_daily_basal":1.8,"max_basal":6.3,"out_units":"mg/dL","min_bg":90,"max_bg":90,"sens":30,"isfProfile":{"units":"mg/dL","user_preferred_units":"mg/dL","sensitivities":[{"i":0,"start":"00:00:00","sensitivity":35,"x":0,"offset":0},{"i":8,"start":"04:00:00","sensitivity":30,"x":1,"offset":240},{"i":20,"start":"10:00:00","sensitivity":30,"x":2,"offset":600,"endOffset":1440}],"first":1},"carb_ratio":9}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
{
"low_reservoir_warn_point": 16,
"keypad_lock_status": 0,
"maxBasal": 6.3,
"temp_basal": {
"percent": 100,
"type": "Units/hour"
},
"low_reservoir_warn_type": 1,
"insulinConcentration": 100,
"audio_bolus_enable": true,
"variable_bolus_enable": true,
"alarm": {
"volume": -1,
"mode": 1
},
"rf_enable": true,
"auto_off_duration_hrs": 15,
"block_enable": false,
"timeformat": 1,
"insulin_action_curve": 3,
"audio_bolus_size": 1.0,
"selected_pattern": 0,
"patterns_enabled": true,
"maxBolus": 12.0,
"paradigm_enabled": 1
}

View file

@ -0,0 +1 @@
{"content":"148-21 16:36\n5.2U->-28-16\nTmp: 28m@0.0 at 16:40\nReq: None\nCOB: 0, Dev: -64, BGI: -8.2, ISF: 21, Target: 81; Eventual BG -28 < 81, setting -11.3U/hr, but 28m left and 0 ~ req 0U/hr: no action required\nSched: 0.60U/hr\nmealCOB: 0g\neddie\n","refresh_frequency":1}

View file

@ -0,0 +1,31 @@
[
{
"duration": "30",
"raw_duration": {
"_type": "TempBasalDuration",
"_description": "TempBasalDuration 2017-01-04T16:37:57 head[2], body[0] op[0x16]",
"timestamp": "2017-01-04T16:37:57+01:00",
"_body": "",
"_head": "1601",
"duration (min)": 30,
"_date": "3965104411"
},
"timestamp": "2017-01-04T16:37:57+01:00",
"absolute": "0",
"rate": 0,
"raw_rate": {
"_type": "TempBasal",
"temp": "absolute",
"_description": "TempBasal 2017-01-04T16:37:57 head[2], body[1] op[0x33]",
"timestamp": "2017-01-04T16:37:57+01:00",
"_body": "00",
"_head": "3300",
"rate": 0,
"_date": "3965104411"
},
"eventType": "Temp Basal",
"medtronic": "mm://openaps/mm-format-ns-treatments/Temp Basal",
"created_at": "2017-01-04T16:37:57+01:00",
"enteredBy": "openaps://medtronic/522"
}
]

View file

@ -0,0 +1 @@
{"device":"openaps://eddie","openaps":{"iob":{"iob":5.521,"activity":0.077,"bolussnooze":1.574,"basaliob":1.893,"netbasalinsulin":5.05,"hightempinsulin":5.1,"timestamp":"2017-01-04T15:37:36.000Z"},"suggested":{"temp":"absolute","bg":148,"tick":-21,"eventualBG":-34,"snoozeBG":17,"COB":0,"IOB":5.521,"reason":"COB: 0, Dev: -64, BGI: -8.24, ISF: 21, Target: 81; Eventual BG -34 < 81, setting -11.1U/hr","duration":30,"rate":0,"timestamp":"2017-01-04T15:37:50.000Z"},"enacted":{"bg":148,"temp":"absolute","snoozeBG":17,"recieved":true,"predBGs":{"IOB":[148,128,109,91,75,59,45,39,39,39,39,39,39]},"rate":0,"reason":"COB: 0, Dev: -64, BGI: -8.24, ISF: 21, Target: 81; Eventual BG -34 < 81, setting -11.1U/hr","COB":0,"eventualBG":-34,"timestamp":"2017-01-04T15:37:56.000Z","duration":30,"tick":-21,"IOB":5.521}},"pump":{"clock":"2017-01-04T16:37:36+01:00","battery":{"status":"normal","voltage":1.45},"reservoir":120.5,"status":{"status":"normal","bolusing":false,"suspended":false,"timestamp":"2017-01-04T15:37:43.000Z"}},"mmtune":{"scanDetails":[["868.372",4,-91],["868.384",5,-81],["868.396",5,-78],["868.408",5,-77],["868.420",5,-76],["868.432",5,-76],["868.444",5,-76],["868.456",5,-76],["868.468",5,-75],["868.480",5,-76],["868.492",5,-76],["868.504",5,-77],["868.516",5,-80],["868.528",5,-86]],"setFreq":868.468,"usedDefault":false,"timestamp":"2017-01-04T15:33:30.000Z"},"uploader":{"battery":57,"batteryVoltage":3748}}

View file

@ -0,0 +1 @@
{"content":"148-21 16:36\n5.2U->-28-16\nTmp: 28m@0.0 at 16:40\nReq: None\nCOB: 0, Dev: -64, BGI: -8.2, ISF: 21, Target: 81; Eventual BG -28 < 81, setting -11.3U/hr, but 28m left and 0 ~ req 0U/hr: no action required\nSched: 0.60U/hr\nmealCOB: 0g\neddie\n","refresh_frequency":1}

View file

@ -3,10 +3,9 @@ package info.nightscout.utils;
import org.json.JSONObject; import org.json.JSONObject;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
/** /**

View file

@ -17,7 +17,12 @@ public class JSONFormatter {
public static Spanned format(final String jsonString) { public static Spanned format(final String jsonString) {
final JsonVisitor visitor = new JsonVisitor(4, ' '); final JsonVisitor visitor = new JsonVisitor(4, ' ');
try { try {
return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0)); if (jsonString.equals("undefined"))
return Html.fromHtml("undefined");
else if (jsonString.getBytes()[0] == '[')
return Html.fromHtml(visitor.visit(new JSONArray(jsonString), 0));
else
return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0));
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
return Html.fromHtml(""); return Html.fromHtml("");

View file

@ -56,7 +56,7 @@ public class Translator {
case "Sensor": case "Sensor":
return MainApp.sResources.getString(R.string.glucosetype_sensor); return MainApp.sResources.getString(R.string.glucosetype_sensor);
case "Manual": case "Manual":
return MainApp.sResources.getString(R.string.glucosetype_manual); return MainApp.sResources.getString(R.string.manual);
} }
return text; return text;
} }

View file

@ -0,0 +1,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="@color/colorWizardButton" />
<stroke android:width="1dip" android:color="@android:color/white"/>
<corners
android:radius="2dp" >
</corners>
</shape>

View file

@ -22,6 +22,19 @@
android:text="@string/careportal_profileswitch" android:text="@string/careportal_profileswitch"
android:textColor="@color/colorProfileSwitchButton" /> android:textColor="@color/colorProfileSwitchButton" />
<Button
android:id="@+id/actions_temptarget"
style="?android:attr/buttonStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="0.5"
android:text="@string/careportal_temptarget"
android:textColor="@color/colorTempTargetButton" />
<Button <Button
android:id="@+id/actions_settempbasal" android:id="@+id/actions_settempbasal"
style="?android:attr/buttonStyle" style="?android:attr/buttonStyle"

Some files were not shown because too many files have changed in this diff Show more