mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
Merge branch 'dev' into wip/announce
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user