Merge branch 'dev' into wip/announce

This commit is contained in:
Jason Calabrese
2015-07-26 15:27:31 -07:00
7 changed files with 87 additions and 42 deletions
+1 -1
View File
@@ -180,7 +180,7 @@ Use the [autoconfigure tool][autoconfigure] to sync an uploader to your config.
* `BWP_SNOOZE_MINS` (`10`) - minutes to snooze when there is enough IOB to cover a high BG.
* `BWP_SNOOZE` - (`0.10`) If BG is higher then the `target_high` and `BWP` < `BWP_SNOOZE` alarms will be snoozed for `BWP_SNOOZE_MINS`.
* `cage` (Cannula Age) - Calculates the number of hours since the last `Site Change` treatment that was recorded.
* `CAGE_ENABLEALERTS` (`false`) - Set to `true` to enable notifications to remind you of upcoming cannula change.
* `CAGE_ENABLE_ALERTS` (`false`) - Set to `true` to enable notifications to remind you of upcoming cannula change.
* `CAGE_INFO` (`44`) - If time since last `Site Change` matches `CAGE_INFO`, user will be warned of upcoming cannula change
* `CAGE_WARN` (`48`) - If time since last `Site Change` matches `CAGE_WARN`, user will be alarmed to to change the cannula
* `CAGE_URGENT` (`72`) - If time since last `Site Change` matches `CAGE_URGENT`, user will be issued a persistent warning of overdue change.
+5 -5
View File
@@ -21,7 +21,7 @@ cage.getPrefs = function getPrefs(sbx) {
'info' : sbx.extendedSettings.info ? sbx.extendedSettings.info : 44,
'warn' : sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 48,
'urgent' : sbx.extendedSettings.urgent ? sbx.extendedSettings.urgent : 72,
'enableAlerts' : sbx.extendedSettings.enablealerts
'enableAlerts' : sbx.extendedSettings.enableAlerts
};
};
@@ -64,8 +64,8 @@ cage.findLatestTimeChange = function findLatestTimeChange(sbx) {
_.forEach(sbx.data.treatments, function eachTreatment (treatment) {
var treatmentDate = treatment.mills;
if (treatment.eventType === 'Site Change' && treatmentDate > prevDate && treatmentDate < sbx.time) {
if (treatment.eventType === 'Site Change' && treatmentDate > prevDate && treatmentDate <= sbx.time) {
prevDate = treatmentDate;
returnValue.treatmentDate = treatmentDate;
@@ -76,12 +76,12 @@ cage.findLatestTimeChange = function findLatestTimeChange(sbx) {
var minFractions = a.diff(b,'minutes') - hours * 60;
returnValue.checkForAlert = minFractions <= 10;
if (!returnValue.found) {
returnValue.found = true;
returnValue.age = hours;
} else {
if (hours > 0 && hours < returnValue.age) {
if (hours >= 0 && hours < returnValue.age) {
returnValue.age = hours;
if (treatment.notes) {
returnValue.message = treatment.notes;
+31 -16
View File
@@ -2,12 +2,13 @@
var _ = require('lodash');
var moment = require('moment-timezone');
var NodeCache = require('node-cache');
function init(profileData) {
function profile() {
return profile;
}
var profile = { };
profile.timeValueCache = new NodeCache({ stdTTL: 600, checkperiod: 600 });
profile.loadData = function loadData(profileData) {
if (profileData && profileData.length) {
@@ -35,17 +36,27 @@ function init(profileData) {
});
};
if (profileData) { profile.loadData(profileData); }
profile.getValueByTime = function getValueByTime (time, valueContainer) {
profile.getValueByTime = function getValueByTime (time, valueType) {
if (!time) { time = Date.now(); }
//round to the minute for better caching
var minuteTime = Math.round(time / 60000) * 60000;
var cacheKey = (minuteTime + valueType);
var returnValue = profile.timeValueCache[cacheKey];
if (returnValue) {
return returnValue;
}
var valueContainer = profile.getCurrentProfile()[valueType];
// Assumes the timestamps are in UTC
// Use local time zone if profile doesn't contain a time zone
// This WILL break on the server; added warnings elsewhere that this is missing
// TODO: Better warnings to user for missing configuration
var t = profile.getTimezone() ? moment(time).tz(profile.getTimezone()) : moment(time);
var t = profile.getTimezone() ? moment(minuteTime).tz(profile.getTimezone()) : moment(minuteTime);
// Convert to seconds from midnight
var mmtMidnight = t.clone().startOf('day');
@@ -53,7 +64,7 @@ function init(profileData) {
// If the container is an Array, assume it's a valid timestamped value container
var returnValue = valueContainer;
returnValue = valueContainer;
if( Object.prototype.toString.call(valueContainer) === '[object Array]' ) {
_.forEach(valueContainer, function eachValue (value) {
@@ -62,6 +73,9 @@ function init(profileData) {
}
});
}
profile.timeValueCache[cacheKey] = returnValue;
return returnValue;
};
@@ -82,35 +96,36 @@ function init(profileData) {
};
profile.getDIA = function getDIA(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['dia']);
return profile.getValueByTime(time, 'dia');
};
profile.getSensitivity = function getSensitivity(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['sens']);
return profile.getValueByTime(time, 'sens');
};
profile.getCarbRatio = function getCarbRatio(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['carbratio']);
return profile.getValueByTime(time, 'carbratio');
};
profile.getCarbAbsorptionRate = function getCarbAbsorptionRate(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['carbs_hr']);
return profile.getValueByTime(time, 'carbs_hr');
};
profile.getLowBGTarget = function getLowBGTarget(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['target_low']);
return profile.getValueByTime(time, 'target_low');
};
profile.getHighBGTarget = function getHighBGTarget(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['target_high']);
return profile.getValueByTime(time, 'target_high');
};
profile.getBasal = function getBasal(time) {
return profile.getValueByTime(time,profile.getCurrentProfile()['basal']);
return profile.getValueByTime(time,'basal');
};
if (profileData) { profile.loadData(profileData); }
return profile();
return profile;
}
module.exports = init;
+1 -1
View File
@@ -2,7 +2,6 @@
var _ = require('lodash');
var units = require('./units')();
var profile = require('./profilefunctions')();
function init ( ) {
var sbx = {};
@@ -45,6 +44,7 @@ function init ( ) {
//don't expose all of notifications, ctx.notifications will decide what to do after all plugins chime in
sbx.notifications = _.pick(ctx.notifications, ['levels', 'requestNotify', 'requestSnooze', 'requestClear']);
var profile = require('./profilefunctions')();
//Plugins will expect the right profile based on time
profile.loadData(ctx.data.profiles);
sbx.data.profile = profile;
+11 -7
View File
@@ -381,13 +381,17 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
var pluginBase = Nightscout.plugins.base(majorPills, minorPills, statusPills, bgStatus, tooltip);
sbx = Nightscout.sandbox.clientInit(app, browserSettings, time, pluginBase, {
sgvs: sgvs
, cals: [cal]
, treatments: treatments
, profile: Nightscout.profile
, uploaderBattery: devicestatusData && devicestatusData.uploaderBattery
});
sbx = Nightscout.sandbox.clientInit(app
, browserSettings
, new Date(time).getTime() //make sure we send a timestamp
, pluginBase, {
sgvs: sgvs
, cals: [cal]
, treatments: treatments
, profile: Nightscout.profile
, uploaderBattery: devicestatusData && devicestatusData.uploaderBattery
}
);
//all enabled plugins get a chance to set properties, even if they aren't shown
Nightscout.plugins.setProperties(sbx);
+26 -1
View File
@@ -44,6 +44,31 @@ describe('cage', function ( ) {
});
it('set a pill to the current cannula age', function (done) {
var app = {};
var clientSettings = {};
var data = {
treatments: [
{eventType: 'Site Change', notes: 'Foo', mills: Date.now() - 48 * 60 * 60000}
, {eventType: 'Site Change', notes: '', mills: Date.now() - 59 * 60000}
]
};
var pluginBase = {
updatePillText: function mockedUpdatePillText (plugin, options) {
options.value.should.equal('0h');
options.info.length.should.equal(1);
done();
}
};
var sbx = sandbox.clientInit(app, clientSettings, Date.now(), pluginBase, data);
cage.updateVisualisation(sbx);
});
it('trigger a warning when cannula is 48 hours old', function (done) {
ctx.notifications.initRequests();
@@ -53,7 +78,7 @@ describe('cage', function ( ) {
ctx.data.treatments = [{eventType: 'Site Change', mills: before}];
var sbx = prepareSandbox();
sbx.extendedSettings = { 'enablealerts': 'TRUE' };
sbx.extendedSettings = { 'enableAlerts': 'TRUE' };
cage.checkNotifications(sbx);
var highest = ctx.notifications.findHighestAlarm();
+12 -11
View File
@@ -70,18 +70,19 @@ describe('Profile', function ( ) {
});
it('should know how to reload data and still know what the low target is with old style profiles', function() {
var profileData2 = {
'dia': 3,
'carbs_hr': 30,
'carbratio': 7,
'sens': 35,
'target_low': 50,
'target_high': 120
};
profile.loadData([profileData2]);
var dia = profile.getLowBGTarget(now);
var profile2 = require('../lib/profilefunctions')([profileData]);
var profileData2 = {
'dia': 3,
'carbs_hr': 30,
'carbratio': 7,
'sens': 35,
'target_low': 50,
'target_high': 120
};
profile2.loadData([profileData2]);
var dia = profile2.getLowBGTarget(now);
dia.should.equal(50);
});