Add an option to enable IOB in the mainline #452
Merged
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
ea1dbcc
forgot to git add some profile api files
7653ef5
no POSTs yet
6080f67
more cherry-picking and porting of the profile api/storage from iob-cob
7f550b8
start getting browserify-express hooked up to expose a shared IOB module
jasoncalabrese 91365a7
Merge branch 'wip/enable-profile' into wip/enable-iob
jasoncalabrese ba05243
use IOB module to display IOB on th chart
jasoncalabrese d9f0c4c
removed debugs
jasoncalabrese a693304
now using new IOB module for /pebble
jasoncalabrese 85a19c7
clean up
jasoncalabrese 5a13393
only load treatments and profile if iob is enabled
jasoncalabrese ee9dcae
more clean up
jasoncalabrese 127e4f5
added mocks for treatments and profile so the pebble test doesn't fail
jasoncalabrese 0aea8a7
very basic IOB test
jasoncalabrese aa9233b
new pill display for BG delta and IOB
jasoncalabrese 508d582
Merge branch 'dev' into wip/enable-iob
jasoncalabrese c1a9bdd
new pill colors from @jimsiff
jasoncalabrese 7fb088c
Merge branch 'dev' into wip/enable-iob
jasoncalabrese 5159859
stop pills from overlapping time in narrow mode
jasoncalabrese 2fc4147
improved iob display and rounding
jasoncalabrese 26786e6
fix iob test to expect new updated iob display value
jasoncalabrese 6134e11
more css hacking for the arrows
jasoncalabrese edfcbc0
more adjustments of pill tops for different screen sizes
jasoncalabrese bf2bac6
some cleanup suggested by @dduugg and some more IOB tests
jasoncalabrese 06235ff
resort package dependencies
jasoncalabrese 7bd9446
move all the browserify bundle config to a new module
jasoncalabrese
Jump to file
No files found.
+3
−0
.gitignore
.gitignore
+12
−0
bundle.source.js
bundle/bundle.source.js
+17
−0
index.js
bundle/index.js
+1
−0
env.js
env.js
+2
−1
index.js
lib/api/index.js
+29
−0
index.js
lib/api/profile/index.js
+80
−0
iob.js
lib/iob.js
+44
−4
pebble.js
lib/pebble.js
+24
−0
profile.js
lib/profile.js
+21
−4
websocket.js
lib/websocket.js
+3
−2
package.json
package.json
+7
−3
server.js
server.js
+53
−13
main.css
static/css/main.css
+3
−2
index.html
static/index.html
+38
−11
client.js
static/js/client.js
+80
−0
iob.test.js
tests/iob.test.js
+14
−2
pebble.test.js
tests/pebble.test.js
| @@ -0,0 +1,12 @@ | ||
| +(function () { | ||
| + | ||
| + window.Nightscout = window.Nightscout || {}; | ||
| + | ||
| + window.Nightscout = { | ||
| + iob: require('../lib/iob')() | ||
| + }; | ||
| + | ||
| + console.info("Nightscout bundle ready", window.Nightscout); | ||
| + | ||
| +})(); | ||
| + |
| @@ -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; |
| @@ -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
lib/iob.js
| @@ -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; |
| @@ -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; |
Oops, something went wrong.