copy basic files oref0 dev 2017/01/04, make it running without crash

This commit is contained in:
Milos Kozak 2017-01-04 22:21:46 +01:00
parent 9d5c2e5dac
commit 8aad003311
7 changed files with 476 additions and 188 deletions

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

@ -12,7 +12,42 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, offline, meal_data, setTempBasal) {
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 var rT = { //short for requestedTemp
}; };
@ -20,17 +55,40 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
rT.error ='Error: could not get current basal rate'; rT.error ='Error: could not get current basal rate';
return rT; 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; var bg = glucose_status.glucose;
if (bg < 38) { //Dexcom is in ??? mode or calibrating, do nothing. Asked @benwest for raw data in iter_glucose // TODO: figure out how to use raw isig data to estimate BG
rT.error = "CGM is calibrating or in ??? state"; if (bg < 39) { //Dexcom is in ??? mode or calibrating
return rT; 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 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 // if target_bg is set, great. otherwise, if min and max are set, then set target to their average
var target_bg; 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') { if (typeof profile.target_bg !== 'undefined') {
target_bg = profile.target_bg; target_bg = profile.target_bg;
} else { } else {
@ -42,61 +100,90 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} }
} }
// 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' ) { if (typeof iob_data === 'undefined' ) {
rT.error ='Error: iob_data undefined'; rT.error ='Error: iob_data undefined';
return rT; return rT;
} }
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' || typeof iob_data.activity === 'undefined') { 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'; rT.error ='Error: iob_data missing some property';
return rT; return rT;
} }
var tick; var tick;
if (glucose_status.delta >= 0) { if (glucose_status.delta > -0.5) {
tick = "+" + glucose_status.delta; tick = "+" + round(glucose_status.delta,0);
} else { } else {
tick = glucose_status.delta; tick = round(glucose_status.delta,0);
} }
var minDelta = Math.min(glucose_status.delta, glucose_status.avgdelta); var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
//var maxDelta = Math.max(glucose_status.delta, glucose_status.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 //calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
var bgi = Math.round(( -iob_data.activity * profile.sens * 5 )*100)/100; var bgi = round(( -iob_data.activity * sens * 5 ), 2);
// project positive deviations for 15 minutes // project deviations for 30 minutes
var deviation = Math.round( 15 / 5 * ( glucose_status.avgdelta - bgi ) ); var deviation = Math.round( 30 / 5 * ( minDelta - bgi ) );
// project negative deviations for 30 minutes // don't overreact to a big negative delta: use minAvgDelta if deviation is negative
if (deviation < 0) { if (deviation < 0) {
deviation = Math.round( 30 / 5 * ( glucose_status.avgdelta - bgi ) ); deviation = Math.round( (30 / 5) * ( minAvgDelta - bgi ) );
} }
//console.log("Avg.Delta: " + glucose_status.avgdelta.toFixed(1) + ", BGI: " + bgi.toFixed(1) + " 15m activity projection: " + deviation.toFixed(0));
// calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity // calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
var naive_eventualBG = Math.round( bg - (iob_data.iob * profile.sens) ); 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 // and adjust it for the deviation above
var eventualBG = naive_eventualBG + deviation; var eventualBG = naive_eventualBG + deviation;
// calculate what portion of that is due to bolussnooze // calculate what portion of that is due to bolussnooze
var bolusContrib = iob_data.bolussnooze * profile.sens; var bolusContrib = iob_data.bolussnooze * sens;
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime // 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 ); var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
// adjust that for deviation like we did eventualBG // adjust that for deviation like we did eventualBG
var snoozeBG = naive_snoozeBG + deviation; var snoozeBG = naive_snoozeBG + deviation;
//console.log("BG: " + bg +"(" + tick + ","+glucose_status.avgdelta.toFixed(1)+")"+ " -> " + eventualBG + "-" + snoozeBG + " (Unadjusted: " + naive_eventualBG + "-" + naive_snoozeBG + "), BGI: " + bgi); var expectedDelta = calculate_expected_delta(profile.dia, target_bg, eventualBG, bgi);
var expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
//console.log("expectedDelta: " + expectedDelta);
if (typeof eventualBG === 'undefined' || isNaN(eventualBG)) { if (typeof eventualBG === 'undefined' || isNaN(eventualBG)) {
rT.error ='Error: could not calculate eventualBG'; rT.error ='Error: could not calculate eventualBG';
return rT; return rT;
} }
// min_bg of 90 -> threshold of 70, 110 -> 80, and 130 -> 90 // min_bg of 90 -> threshold of 70, 110 -> 80, and 130 -> 90
var threshold = profile.min_bg - 0.5*(profile.min_bg-50); var threshold = min_bg - 0.5*(min_bg-50);
rT = { rT = {
'temp': 'absolute' 'temp': 'absolute'
@ -109,208 +196,292 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var basaliob; var basaliob;
if (iob_data.basaliob) { basaliob = iob_data.basaliob; } if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; } else { basaliob = iob_data.iob - iob_data.bolussnooze; }
// allow meal assist to run when carbs are just barely covered
if (minDelta > Math.max(3, bgi) && ( (meal_data.carbs > 0 && (1.1 * meal_data.carbs/profile.carb_ratio > meal_data.boluses + basaliob)) || ( deviation > 25 && minDelta > 7 ) ) ) { // generate predicted future BGs based on IOB, COB, and current absortpion rate
// ignore all covered IOB, and just set eventualBG to the current bg
eventualBG = Math.max(bg,eventualBG) + deviation; var COBpredBGs = [];
rT.eventualBG = eventualBG; var aCOBpredBGs = [];
profile.min_bg = 80; var IOBpredBGs = [];
target_bg = (profile.min_bg + profile.max_bg) / 2; COBpredBGs.push(bg);
expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10; aCOBpredBGs.push(bg);
rT.mealAssist = "On: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi; IOBpredBGs.push(bg);
} else { //console.error(meal_data);
rT.mealAssist = "Off: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi; // 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);
} }
if (bg < threshold) { // low glucose suspend mode: BG is < ~80 aci = 10;
rT.reason = "BG " + bg + "<" + threshold; //5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m)
if ((glucose_status.delta <= 0 && glucose_status.avgdelta <= 0) || (glucose_status.delta < expectedDelta && glucose_status.avgdelta < expectedDelta)) { cid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / ci;
// BG is still falling / rising slower than predicted acid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / aci;
return setTempBasal(0, 30, profile, rT, offline); 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(); }
} }
if (glucose_status.delta > glucose_status.avgdelta) { 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"; rT.reason += ", delta " + glucose_status.delta + ">0";
} else { } else {
rT.reason += ", avg delta " + glucose_status.avgdelta.toFixed(2) + ">0"; rT.reason += ", min delta " + minDelta.toFixed(2) + ">0";
} }
if (currenttemp.rate > profile.current_basal) { // if a high-temp is running if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", cancel high temp"; rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return setTempBasal(0, 0, profile, rT, offline); // cancel high temp return rT;
} else if (currenttemp.duration && eventualBG > profile.max_bg) { // if low-temped and predicted to go high from negative IOB
rT.reason += ", cancel low temp";
return setTempBasal(0, 0, profile, rT, offline); // cancel low temp
}
rT.reason += "; no high-temp to cancel";
return rT;
}
if (eventualBG < profile.min_bg) { // if eventual BG is below target:
if (rT.mealAssist.indexOf("On") == 0) {
rT.reason = "Meal assist: " + meal_data.carbs + "g, " + meal_data.boluses + "U";
} else { } else {
rT.reason = "Eventual BG " + eventualBG + "<" + profile.min_bg; rT.reason += "; setting current basal of " + basal + " as temp";
// if 5m or 15m avg BG is rising faster than expected delta return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
if (minDelta > expectedDelta && minDelta > 0) { }
if (glucose_status.delta > glucose_status.avgdelta) { }
rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
} else { if (eventualBG < min_bg) { // if eventual BG is below target:
rT.reason += ", but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " > Exp. Delta " + expectedDelta; 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 (currenttemp.duration > 0) { // if there is currently any temp basal running if (minDelta > expectedDelta && minDelta > 0) {
rT.reason = rT.reason += "; cancel"; if (glucose_status.delta > minDelta) {
return setTempBasal(0, 0, profile, rT, offline); // cancel temp rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
} else { } else {
rT.reason = rT.reason += "; no temp to cancel"; 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; return rT;
} } else {
rT.reason += "; setting current basal of " + basal + " as temp";
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
} }
} }
if (eventualBG < profile.min_bg) { if (eventualBG < min_bg) {
// if this is just due to boluses, we can snooze until the bolus IOB decays (at double speed) // if we've bolused recently, we can snooze until the bolus IOB decays (at double speed)
if (snoozeBG > profile.min_bg) { // if adding back in the bolus contribution BG would be above min if (snoozeBG > min_bg) { // if adding back in the bolus contribution BG would be above min
// if BG is falling and high-temped, or rising and low-temped, cancel rT.reason += ", bolus snooze: eventual BG range " + convert_bg(eventualBG, profile) + "-" + convert_bg(snoozeBG, profile);
// compare against zero here, not BGI, because BGI will be highly negative from boluses and no carbs //console.error(currenttemp, basal );
if (glucose_status.delta < 0 && currenttemp.duration > 0 && currenttemp.rate > profile.current_basal) { if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += tick + ", and temp " + currenttemp.rate + " > basal " + profile.current_basal; rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp return rT;
} else if (glucose_status.delta > 0 && currenttemp.duration > 0 && currenttemp.rate < profile.current_basal) { } else {
rT.reason += tick + ", and temp " + currenttemp.rate + " < basal " + profile.current_basal; rT.reason += "; setting current basal of " + basal + " as temp";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
} }
rT.reason += ", bolus snooze: eventual BG range " + eventualBG + "-" + snoozeBG;
return rT;
} else { } else {
// calculate 30m low-temp required to get projected BG up to target // 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 // 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 // multiply by 2 to low-temp faster for increased hypo safety
var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / profile.sens); var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / sens);
if (minDelta < 0 && minDelta > expectedDelta) { if (minDelta < 0 && minDelta > expectedDelta) {
// if we're barely falling, newinsulinReq should be barely negative // if we're barely falling, newinsulinReq should be barely negative
rT.reason += ", Snooze BG " + snoozeBG; rT.reason += ", Snooze BG " + convert_bg(snoozeBG, profile);
var newinsulinReq = Math.round(( insulinReq * (minDelta / expectedDelta) ) * 100)/100; var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
//console.log("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq); //console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq; insulinReq = newinsulinReq;
} }
// rate required to deliver insulinReq less insulin over 30m: // rate required to deliver insulinReq less insulin over 30m:
var rate = profile.current_basal + (2 * insulinReq); var rate = basal + (2 * insulinReq);
rate = Math.round( rate * 1000 ) / 1000; rate = round_basal(rate, profile);
// if required temp < existing temp basal // if required temp < existing temp basal
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60; var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled < insulinReq - 0.2) { // if current temp would deliver >0.2U less than the required insulin, raise the rate 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 - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-0.2U"; rT.reason += ", "+currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-" + basal*0.3;
return setTempBasal(rate, 30, profile, rT, offline); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
} }
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate > currenttemp.rate - 0.1)) { if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate >= currenttemp.rate * 0.8)) {
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr"; rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
return rT; return rT;
} else { } else {
rT.reason += ", setting " + rate + "U/hr"; rT.reason += ", setting " + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline); 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 eventual BG is above min but BG is falling faster than expected Delta
if (minDelta < expectedDelta) { if (minDelta < expectedDelta) {
if (glucose_status.delta < glucose_status.avgdelta) { if (glucose_status.delta < minDelta) {
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Delta " + tick + " < Exp. Delta " + expectedDelta; rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Delta " + tick + " < Exp. Delta " + expectedDelta;
} else { } else {
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " < Exp. Delta " + expectedDelta; 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 > 0) { // if there is currently any temp basal running if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason = rT.reason += "; cancel"; rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp return rT;
} else { } else {
rT.reason = rT.reason += "; no temp to cancel"; 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; return rT;
} }
}
if (eventualBG < profile.max_bg) { rT.reason += convert_bg(eventualBG, profile)+"-"+convert_bg(snoozeBG, profile)+" in range: no temp required";
rT.reason = eventualBG + " is in range. No temp required"; if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
if (currenttemp.duration > 0) { // if there is currently any temp basal running rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
rT.reason = rT.reason += "; cancel";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
}
if (offline == 'Offline') {
// if no temp is running or required, set the current basal as a temp, so you can see on the pump that the loop is working
if ((!currenttemp.duration || (currenttemp.rate == profile.current_basal)) && !rT.duration) {
rT.reason = rT.reason + "; setting current basal of " + profile.current_basal + " as temp";
return setTempBasal(profile.current_basal, 30, profile, rT, offline);
}
}
return rT;
}
if (snoozeBG < profile.max_bg) {
rT.reason = snoozeBG + " < " + profile.max_bg;
if (currenttemp.duration > 0) { // if there is currently any temp basal running
rT.reason = rT.reason += "; cancel";
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
} else {
rT.reason = rT.reason += "; no temp to cancel";
return rT; 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: // eventual BG is at/above target:
// if iob is over max, just cancel any temps // if iob is over max, just cancel any temps
var basaliob; var basaliob;
if (iob_data.basaliob) { basaliob = iob_data.basaliob; } if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; } else { basaliob = iob_data.iob - iob_data.bolussnooze; }
rT.reason = "Eventual BG " + eventualBG + ">=" + profile.max_bg + ", "; rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " >= " + convert_bg(max_bg, profile) + ", ";
if (basaliob > max_iob) { if (basaliob > max_iob) {
rT.reason = "basaliob " + basaliob + " > max_iob " + max_iob; rT.reason += "basaliob " + round(basaliob,2) + " > max_iob " + max_iob;
return setTempBasal(0, 0, profile, rT, offline); 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 } 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: // 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 // if in meal assist mode, check if snoozeBG is lower, as eventualBG is not dependent on IOB
var insulinReq = (Math.min(snoozeBG,eventualBG) - target_bg) / profile.sens; var insulinReq = round( (Math.min(snoozeBG,eventualBG) - target_bg) / sens, 2);
if (minDelta < 0 && minDelta > expectedDelta) { if (minDelta < 0 && minDelta > expectedDelta) {
var newinsulinReq = Math.round(( insulinReq * (1 - (minDelta / expectedDelta)) ) * 100)/100; var newinsulinReq = round(( insulinReq * (1 - (minDelta / expectedDelta)) ), 2);
//console.log("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq); //console.error("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq);
insulinReq = newinsulinReq; insulinReq = newinsulinReq;
} }
// if that would put us over max_iob, then reduce accordingly // if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-basaliob) { if (insulinReq > max_iob-basaliob) {
rT.reason = "max_iob " + max_iob + ", "; rT.reason += "max_iob " + max_iob + ", ";
insulinReq = max_iob-basaliob; insulinReq = max_iob-basaliob;
} }
// rate required to deliver insulinReq more insulin over 30m: // rate required to deliver insulinReq more insulin over 30m:
var rate = profile.current_basal + (2 * insulinReq); var rate = basal + (2 * insulinReq);
rate = Math.round( rate * 1000 ) / 1000; rate = round_basal(rate, profile);
// var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * basal);
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
if (rate > maxSafeBasal) { if (rate > maxSafeBasal) {
rT.reason += "adj. req. rate:"+rate.toFixed(1) +" to maxSafeBasal:"+maxSafeBasal.toFixed(1)+", "; rT.reason += "adj. req. rate: "+rate+" to maxSafeBasal: "+maxSafeBasal+", ";
rate = maxSafeBasal; rate = round_basal(maxSafeBasal, profile);
} }
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60; var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled > insulinReq + 0.2) { // if current temp would deliver >0.2U more than the required insulin, lower the rate 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 - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > req " + insulinReq + "+0.2U"; rT.reason += currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > 2 * req " + insulinReq + ". Setting temp basal of " + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
} }
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr"; rT.reason += "no temp, setting " + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
} }
if (currenttemp.duration > 5 && rate < currenttemp.rate + 0.1) { // if required temp <~ existing temp basal 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"; rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr";
return rT; return rT;
} }
// required temp > existing temp basal // required temp > existing temp basal
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr"; rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr";
return setTempBasal(rate, 30, profile, rT, offline); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
} }
}; };
module.exports = determine_basal; 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

@ -209,10 +209,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
/* /*
* Returns glucose_status for openAPS or null if no actual data available * Returns glucose_status for openAPS or null if no actual data available
*/ */
public static class GlucoseStatus implements Parcelable { public static class GlucoseStatus {
public double glucose = 0d; public double glucose = 0d;
public double delta = 0d; public double delta = 0d;
public double avgdelta = 0d; public double avgdelta = 0d;
public double short_avgdelta = 0d; // TODO: add calculation for AMA
public double long_avgdelta = 0d; // TODO: add calculation for AMA
@Override @Override
public String toString() { public String toString() {
@ -227,34 +229,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
"<b>" + MainApp.sResources.getString(R.string.avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl"); "<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() {
} }

View file

@ -34,21 +34,24 @@ public class DetermineBasalAdapterAMAJS {
private V8Object mIobData; private V8Object mIobData;
private V8Object mMealData; private V8Object mMealData;
private V8Object mCurrentTemp; private V8Object mCurrentTemp;
private V8Object mAutosensData = null;
private final String PARAM_currentTemp = "currentTemp"; private final String PARAM_currentTemp = "currentTemp";
private final String PARAM_iobData = "iobData"; private final String PARAM_iobData = "iobData";
private final String PARAM_glucoseStatus = "glucose_status"; private final String PARAM_glucoseStatus = "glucose_status";
private final String PARAM_profile = "profile"; private final String PARAM_profile = "profile";
private final String PARAM_meal_data = "meal_data"; private final String PARAM_meal_data = "meal_data";
private final String PARAM_autosens_data = "autosens_data";
private String storedCurrentTemp = null; private String storedCurrentTemp = null;
public String storedIobData = null; private String storedIobData = null;
private String storedGlucoseStatus = null; private String storedGlucoseStatus = null;
private String storedProfile = null; private String storedProfile = null;
private String storedMeal_data = null; private String storedMeal_data = null;
private String storedAutosens_data = null;
/** /**
* Main code * Main code
*/ */
public DetermineBasalAdapterAMAJS(ScriptReader scriptReader) throws IOException { public DetermineBasalAdapterAMAJS(ScriptReader scriptReader) throws IOException {
@ -102,17 +105,22 @@ public class DetermineBasalAdapterAMAJS {
mMealData = new V8Object(mV8rt); mMealData = new V8Object(mV8rt);
mMealData.add("carbs", 0); mMealData.add("carbs", 0);
mMealData.add("boluses", 0); mMealData.add("boluses", 0);
mMealData.add("mealCOB", 0.0d);
mV8rt.add(PARAM_meal_data, mMealData); mV8rt.add(PARAM_meal_data, mMealData);
// Autosens data
mV8rt.executeVoidScript("autosens_data = undefined");
} }
public DetermineBasalResultAMA invoke() { public DetermineBasalResultAMA 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" +
"JSON.stringify(" + PARAM_currentTemp + ")+ \", \" +\n" + "JSON.stringify(" + PARAM_currentTemp + ")+ \", \" +\n" +
"JSON.stringify(" + PARAM_iobData + ")+ \", \" +\n" + "JSON.stringify(" + PARAM_iobData + ")+ \", \" +\n" +
"JSON.stringify(" + PARAM_profile + ")+ \", \" +\n" + "JSON.stringify(" + PARAM_profile + ")+ \", \" +\n" +
"JSON.stringify(" + PARAM_meal_data + ")+ \") \");" "JSON.stringify(" + PARAM_autosens_data + ")+ \", \" +\n" +
"JSON.stringify(" + PARAM_meal_data + ")+ \") \");"
); );
mV8rt.executeVoidScript( mV8rt.executeVoidScript(
"var rT = determine_basal(" + "var rT = determine_basal(" +
@ -120,9 +128,9 @@ public class DetermineBasalAdapterAMAJS {
PARAM_currentTemp + ", " + PARAM_currentTemp + ", " +
PARAM_iobData + ", " + PARAM_iobData + ", " +
PARAM_profile + ", " + PARAM_profile + ", " +
"undefined, " + PARAM_autosens_data + ", " +
PARAM_meal_data + ", " + PARAM_meal_data + ", " +
"setTempBasal" + "tempBasalFunctions" +
");"); ");");
@ -144,6 +152,8 @@ public class DetermineBasalAdapterAMAJS {
storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");"); storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");");
storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");"); storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");");
storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");"); storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");");
if (mAutosensData != null)
storedAutosens_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_autosens_data + ");");
return result; return result;
} }
@ -168,10 +178,21 @@ public class DetermineBasalAdapterAMAJS {
return storedMeal_data; return storedMeal_data;
} }
String getAutosensDataParam() {
return storedAutosens_data;
}
private void loadScript() throws IOException { 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( mV8rt.executeVoidScript(
readFile("OpenAPSAMA/determine-basal.js"), readFile("OpenAPSAMA/determine-basal.js"),
"OpenAPSAMA/bin/oref0-determine-basal.js", "OpenAPSAMA/determine-basal.js",
0); 0);
mV8rt.executeVoidScript("var determine_basal = module.exports;"); mV8rt.executeVoidScript("var determine_basal = module.exports;");
mV8rt.executeVoidScript( mV8rt.executeVoidScript(
@ -228,7 +249,8 @@ public class DetermineBasalAdapterAMAJS {
PumpInterface pump, PumpInterface pump,
IobTotal iobData, IobTotal iobData,
DatabaseHelper.GlucoseStatus glucoseStatus, DatabaseHelper.GlucoseStatus glucoseStatus,
TreatmentsPlugin.MealData mealData) { TreatmentsPlugin.MealData mealData,
JSONObject autosensData) {
String units = profile.getUnits(); String units = profile.getUnits();
@ -258,18 +280,31 @@ public class DetermineBasalAdapterAMAJS {
mGlucoseStatus.add("glucose", glucoseStatus.glucose); mGlucoseStatus.add("glucose", glucoseStatus.glucose);
mGlucoseStatus.add("delta", glucoseStatus.delta); mGlucoseStatus.add("delta", glucoseStatus.delta);
mGlucoseStatus.add("avgdelta", glucoseStatus.avgdelta); mGlucoseStatus.add("avgdelta", glucoseStatus.avgdelta);
mGlucoseStatus.add("short_avgdelta", glucoseStatus.short_avgdelta);
mGlucoseStatus.add("long_avgdelta", glucoseStatus.long_avgdelta);
mMealData.add("carbs", mealData.carbs); mMealData.add("carbs", mealData.carbs);
mMealData.add("boluses", mealData.boluses); mMealData.add("boluses", mealData.boluses);
mMealData.add("mealCOB", mealData.mealCOB);
if (autosensData != null) {
mAutosensData = new V8Object(mV8rt);
// TODO: add autosens data here for AMA
} else {
mV8rt.executeVoidScript("autosens_data = undefined");
}
} }
public void release() { public void release() {
mProfile.release(); mProfile.release();
mCurrentTemp.release(); mCurrentTemp.release();
mIobData.release(); mIobData.release();
mMealData.release(); mMealData.release();
mGlucoseStatus.release(); mGlucoseStatus.release();
if (mAutosensData != null) {
mAutosensData.release();
}
mV8rt.release(); mV8rt.release();
} }

View file

@ -188,7 +188,7 @@ public class OpenAPSAMAPlugin 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;
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData); determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData, null);
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke(); DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();

View file

@ -141,6 +141,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
public class MealData { public class MealData {
public double boluses = 0d; public double boluses = 0d;
public double carbs = 0d; public double carbs = 0d;
public double mealCOB = 0.0d; // TODO: add calculation for AMA
} }
@Override @Override