Skip to content

Commit

Permalink
Merge pull request #452 from nightscout/wip/enable-iob
Browse files Browse the repository at this point in the history
Add an option to enable IOB in the mainline
  • Loading branch information
jasoncalabrese committed Mar 8, 2015
2 parents d90acea + 7bd9446 commit 1e27704
Show file tree
Hide file tree
Showing 17 changed files with 431 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
bower_components/
node_modules/


bundle/bundle.out.js

.idea/
*.iml
my.env
Expand Down
12 changes: 12 additions & 0 deletions bundle/bundle.source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(function () {

window.Nightscout = window.Nightscout || {};

window.Nightscout = {
iob: require('../lib/iob')()
};

console.info("Nightscout bundle ready", window.Nightscout);

})();

17 changes: 17 additions & 0 deletions bundle/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

var browserify_express = require('browserify-express');

function bundle() {
return browserify_express({
entry: __dirname + '/bundle.source.js',
watch: [__dirname + '../lib/', __dirname + '/bundle.source.js'],
mount: '/public/js/bundle.js',
verbose: true,
//minify: true,
bundle_opts: { debug: true }, // enable inline sourcemap on js files
write_file: __dirname + '/bundle.out.js'
});
}

module.exports = bundle;
1 change: 1 addition & 0 deletions env.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function config ( ) {
env.mongo_collection = readENV('MONGO_COLLECTION', 'entries');
env.settings_collection = readENV('MONGO_SETTINGS_COLLECTION', 'settings');
env.treatments_collection = readENV('MONGO_TREATMENTS_COLLECTION', 'treatments');
env.profile_collection = readENV('MONGO_PROFILE_COLLECTION', 'profile');
env.devicestatus_collection = readENV('MONGO_DEVICESTATUS_COLLECTION', 'devicestatus');

env.enable = readENV('ENABLE');
Expand Down
3 changes: 2 additions & 1 deletion lib/api/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

function create (env, entries, settings, treatments, devicestatus) {
function create (env, entries, settings, treatments, profile, devicestatus) {
var express = require('express'),
app = express( )
;
Expand Down Expand Up @@ -47,6 +47,7 @@ function create (env, entries, settings, treatments, devicestatus) {
app.use('/', require('./entries/')(app, wares, entries));
app.use('/', require('./settings/')(app, wares, settings));
app.use('/', require('./treatments/')(app, wares, treatments));
app.use('/', require('./profile/')(app, wares, profile));
app.use('/', require('./devicestatus/')(app, wares, devicestatus));

// Status
Expand Down
29 changes: 29 additions & 0 deletions lib/api/profile/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

var consts = require('../../constants');

function configure (app, wares, profile) {
var express = require('express'),
api = express.Router( );

// invoke common middleware
api.use(wares.sendJSONStatus);
// text body types get handled as raw buffer stream
api.use(wares.bodyParser.raw( ));
// json body types get handled as parsed json
api.use(wares.bodyParser.json( ));
// also support url-encoded content-type
api.use(wares.bodyParser.urlencoded({ extended: true }));

// List settings available
api.get('/profile/', function(req, res) {
profile.list(function (err, attribute) {
return res.json(attribute);
});
});

return api;
}

module.exports = configure;

80 changes: 80 additions & 0 deletions lib/iob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

function calcTotal(treatments, profile, time) {

console.info("trying to calc");

var iob = 0
, activity = 0;

if (!treatments) return {};

if (profile === undefined) {
//if there is no profile default to 3 hour dia
profile = {dia: 3, sens: 0};
}

if (time === undefined) {
time = new Date();
}

treatments.forEach(function (treatment) {
if (new Date(treatment.created_at) < time) {
var tIOB = calcTreatment(treatment, profile, time);
if (tIOB && tIOB.iobContrib) iob += tIOB.iobContrib;
if (tIOB && tIOB.activityContrib) activity += tIOB.activityContrib;
}
});

return {
iob: iob,
display: iob.toFixed(2),
activity: activity
};
}

function calcTreatment(treatment, profile, time) {

var dia = profile.dia
, scaleFactor = 3.0 / dia
, peak = 75
, sens = profile.sens
, iobContrib = 0
, activityContrib = 0;

if (treatment.insulin) {
var bolusTime = new Date(treatment.created_at);
var minAgo = scaleFactor * (time - bolusTime) / 1000 / 60;

if (minAgo < peak) {
var x = minAgo / 5 + 1;
iobContrib = treatment.insulin * (1 - 0.001852 * x * x + 0.001852 * x);
activityContrib = sens * treatment.insulin * (2 / dia / 60 / peak) * minAgo;

} else if (minAgo < 180) {
var x = (minAgo - 75) / 5;
iobContrib = treatment.insulin * (0.001323 * x * x - .054233 * x + .55556);
activityContrib = sens * treatment.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * dia - peak));
} else {
iobContrib = 0;
activityContrib = 0;
}

}

return {
iobContrib: iobContrib,
activityContrib: activityContrib
};

}

function IOB(opts) {

return {
calcTotal: calcTotal
};

}

module.exports = IOB;
48 changes: 44 additions & 4 deletions lib/pebble.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ var DIRECTIONS = {
, 'RATE OUT OF RANGE': 9
};

var iob = require("./iob")();

function directionToTrend (direction) {
var trend = 8;
if (direction in DIRECTIONS) {
Expand All @@ -23,6 +25,8 @@ function pebble (req, res) {
var ONE_DAY = 24 * 60 * 60 * 1000;
var useMetricBg = (req.query.units === "mmol");
var uploaderBattery;
var treatmentResults;
var profileResult;

function scaleBg(bg) {
if (useMetricBg) {
Expand Down Expand Up @@ -74,8 +78,11 @@ function pebble (req, res) {
var count = parseInt(req.query.count) || 1;

var bgs = sgvData.slice(0, count);
//for compatibility we're keeping battery here, but it would be better somewhere else
//for compatibility we're keeping battery and iob here, but they would be better somewhere else
bgs[0].battery = uploaderBattery ? "" + uploaderBattery : undefined;
if (req.iob) {
bgs[0].iob = iob.calcTotal(treatmentResults.slice(0, 20), profileResult, new Date(now)).display;
}

var result = { status: [ {now:now}], bgs: bgs, cals: calData.slice(0, count) };
res.setHeader('content-type', 'application/json');
Expand All @@ -91,15 +98,48 @@ function pebble (req, res) {
}

var earliest_data = Date.now() - ONE_DAY;
var q = { find: {"date": {"$gte": earliest_data}} };
req.entries.list(q, get_latest);
loadTreatments(req, earliest_data, function (err, trs) {
treatmentResults = trs;
loadProfile(req, function (err, profileResults) {
profileResults.forEach(function(profile) {
if (profile) {
if (profile.dia) {
profileResult = profile;
}
}
});
var q = { find: {"date": {"$gte": earliest_data}} };
req.entries.list(q, get_latest);
});
});
});
}
function configure (entries, devicestatus, env) {

function loadTreatments(req, earliest_data, fn) {
if (req.iob) {
var q = { find: {"created_at": {"$gte": new Date(earliest_data).toISOString()}} };
req.treatments.list(q, fn);
} else {
fn(null, []);
}
}

function loadProfile(req, fn) {
if (req.iob) {
req.profile.list(fn);
} else {
fn(null, []);
}
}

function configure (entries, treatments, profile, devicestatus, env) {
function middle (req, res, next) {
req.entries = entries;
req.treatments = treatments;
req.profile = profile;
req.devicestatus = devicestatus;
req.rawbg = env.enable && env.enable.indexOf('rawbg') > -1;
req.iob = env.enable && env.enable.indexOf('iob') > -1;
next( );
}
return [middle, pebble];
Expand Down
24 changes: 24 additions & 0 deletions lib/profile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

function configure (collection, storage) {

function create (obj, fn) {
obj.created_at = (new Date( )).toISOString( );
api( ).insert(obj, function (err, doc) {
fn(null, doc);
});
}

function list (fn) {
return api( ).find({ }).sort({created_at: -1}).toArray(fn);
}

function api ( ) {
return storage.pool.db.collection(collection);
}

api.list = list;
api.create = create;
return api;
}
module.exports = configure;
25 changes: 21 additions & 4 deletions lib/websocket.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

function websocket (env, server, entries, treatments) {
function websocket (env, server, entries, treatments, profiles) {
"use strict";
// CONSTANTS
var ONE_HOUR = 3600000,
Expand Down Expand Up @@ -29,6 +29,7 @@ var dir2Char = {
treatmentData = [],
mbgData = [],
calData = [],
profileData = [],
patientData = [];

function start ( ) {
Expand Down Expand Up @@ -146,6 +147,7 @@ function update() {
cgmData = [];
treatmentData = [];
mbgData = [];
profileData = [];
var earliest_data = now - TWO_DAYS;
var q = { find: {"date": {"$gte": earliest_data}} };
entries.list(q, function (err, results) {
Expand Down Expand Up @@ -188,8 +190,19 @@ function update() {
treatment.x = timestamp.getTime();
return treatment;
});
// all done, do loadData
loadData( );

profiles.list(function (err, results) {
// There should be only one document in the profile collection with a DIA. If there are multiple, use the last one.
results.forEach(function(element, index, array) {
if (element) {
if (element.dia) {
profileData[0] = element;
}
}
});
// all done, do loadData
loadData( );
});
});
});

Expand Down Expand Up @@ -237,6 +250,10 @@ function loadData() {
});
}

if (profileData) {
var profile = profileData;
}

if (actualCurrent && actualCurrent < 39) errorCode = actualCurrent;

var actualLength = actual.length - 1;
Expand Down Expand Up @@ -271,7 +288,7 @@ function loadData() {

// consolidate and send the data to the client
var shouldEmit = is_different(actual, predicted, mbg, treatment, cal);
patientData = [actual, predicted, mbg, treatment, cal];
patientData = [actual, predicted, mbg, treatment, profile, cal];
console.log('patientData', patientData.length);
if (shouldEmit) {
emitData( );
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@
"dependencies": {
"body-parser": "^1.4.3",
"bower": "^1.3.8",
"browserify-express": "^0.1.4",
"errorhandler": "^1.1.1",
"event-stream": "~3.1.5",
"express": "^4.6.1",
"express-extension-to-accept": "0.0.2",
"git-rev": "git://github.com/bewest/git-rev.git",
"mongodb": "^1.4.7",
"moment": "2.8.1",
"pushover-notifications": "0.2.0",
"sgvdata": "0.0.2",
"socket.io": "^0.9.17",
"git-rev": "git://github.com/bewest/git-rev.git"
"socket.io": "^0.9.17"
},
"devDependencies": {
"istanbul": "~0.3.5",
Expand Down
Loading

0 comments on commit 1e27704

Please sign in to comment.