Skip to content

Instantly share code, notes, and snippets.

@scottleibrand
Created September 5, 2015 05:04
Show Gist options
  • Save scottleibrand/b15de1d1e7807023010a to your computer and use it in GitHub Desktop.
Save scottleibrand/b15de1d1e7807023010a to your computer and use it in GitHub Desktop.
diff --git a/env.js b/env.js
index c063c22..9e2c0eb 100644
--- a/env.js
+++ b/env.js
@@ -43,6 +43,7 @@ function config ( ) {
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.pumphistory_collection = readENV('MONGO_PUMPHISTORY_COLLECTION', 'pump');
env.enable = readENV('ENABLE');
env.SSL_KEY = readENV('SSL_KEY');
diff --git a/lib/api/index.js b/lib/api/index.js
index 9943061..3cc7eac 100644
--- a/lib/api/index.js
+++ b/lib/api/index.js
@@ -1,6 +1,6 @@
'use strict';
-function create (env, entries, settings, treatments, profile, devicestatus) {
+function create (env, entries, settings, treatments, profile, devicestatus, pumphistory) {
var express = require('express'),
app = express( )
;
@@ -49,6 +49,7 @@ function create (env, entries, settings, treatments, profile, devicestatus) {
app.use('/', require('./treatments/')(app, wares, treatments));
app.use('/', require('./profile/')(app, wares, profile));
app.use('/', require('./devicestatus/')(app, wares, devicestatus));
+ app.use('/', require('./pumphistory/')(app, wares, pumphistory));
// Status
app.use('/', require('./status')(app, wares));
diff --git a/lib/api/pumphistory/index.js b/lib/api/pumphistory/index.js
new file mode 100644
index 0000000..61eb4c9
--- /dev/null
+++ b/lib/api/pumphistory/index.js
@@ -0,0 +1,47 @@
+'use strict';
+
+var consts = require('../../constants');
+
+function configure (app, wares, pumphistory) {
+ 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('/pumphistory/', function(req, res) {
+ pumphistory.list({}, function (err, pumphistory) {
+ return res.json(pumphistory);
+ });
+ });
+
+ function config_authed (app, api, wares, pumphistory) {
+
+ api.post('/pumphistory/', /*TODO: auth disabled for now, need to get login figured out... wares.verifyAuthorization, */ function(req, res) {
+ var pumprecord = req.body;
+ pumphistory.create(pumprecord, function (err, created) {
+ if (err)
+ res.sendJSONStatus(res, consts.HTTP_INTERNAL_ERROR, 'Mongo Error', err);
+ else
+ res.json(created);
+ });
+ });
+
+ }
+
+ if (app.enabled('api')) {
+ config_authed(app, api, wares, pumphistory);
+ }
+
+ return api;
+}
+
+module.exports = configure;
+
diff --git a/lib/pumphistory.js b/lib/pumphistory.js
new file mode 100644
index 0000000..ffafb2e
--- /dev/null
+++ b/lib/pumphistory.js
@@ -0,0 +1,34 @@
+'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 (opts, fn) {
+ function find ( ) {
+ var q = opts && opts.find ? opts.find : { };
+ return q;
+ }
+
+ return api( ).find(find()).sort({created_at: -1}).toArray(fn);
+ }
+ /*
+ 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;
diff --git a/lib/websocket.js b/lib/websocket.js
index e5c3e50..369cfc5 100644
--- a/lib/websocket.js
+++ b/lib/websocket.js
@@ -1,5 +1,5 @@
-function websocket (env, server, entries, treatments, profiles) {
+function websocket (env, server, entries, treatments, profiles, pumphistory) {
"use strict";
// CONSTANTS
var ONE_HOUR = 3600000,
@@ -33,7 +33,8 @@ var dir2Char = {
mbgData = [],
calData = [],
profileData = [],
- patientData = [];
+ patientData = [],
+ pumpData = [];
function start ( ) {
io = require('socket.io').listen(server);
@@ -151,6 +152,7 @@ function update() {
treatmentData = [];
mbgData = [];
profileData = [];
+ pumpData = [];
var earliest_data = now - dataRange;
var q = { find: {"date": {"$gte": earliest_data}} };
@@ -197,16 +199,43 @@ function update() {
});
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) {
+ // 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( );
+ }
+ });
+ var pq = { find: {"date": {"$gte": (earliest_data - (ONE_DAY / 2))}} };
+ /*
+ console.log(pq);
+ console.log(pumphistory.list);
+ pumphistory.list(pq, function (err, results) {
+ pumpData = results.map(function(pumpRecord) {
+ var timestamp = new Date(pumpRecord.timestamp || pumpRecord.created_at);
+ pumpRecord.x = timestamp.getTime();
+ console.log(pumpRecord);
+ return pumpRecord;
+ });
+ });
+ */
+ pumphistory.list(pq, function (err, results) {
+ pumpData = results;
+ /*
+ console.log(pumpData);
+ });
+ pumphistory.list(pq, function (err, results) {
+ console.log(results);
+ results.forEach(function(element, index, array) {
+ console.log(element);
+ });
+ */
+
+ // all done, do loadData
+ loadData( );
+
+ });
});
});
});
@@ -223,6 +252,7 @@ function loadData() {
treatment = [],
mbg = [],
cal = [],
+ pump = [],
errorCode;
if (cgmData) {
@@ -259,6 +289,13 @@ function loadData() {
var profile = profileData;
}
+ if (pumpData) {
+ pump = pumpData.slice(pumpData.length-400, pumpData.length);
+ pump.sort(function(a, b) {
+ return a.date - b.date;
+ });
+ }
+
if (actualCurrent && actualCurrent < 39) errorCode = actualCurrent;
var actualLength = actual.length - 1;
@@ -294,8 +331,8 @@ function loadData() {
//TODO: need to consider when data being sent has less than the 2 day minimum
// consolidate and send the data to the client
- var shouldEmit = is_different(actual, predicted, mbg, treatment, cal);
- patientData = [actual, predicted, mbg, treatment, profile, cal];
+ var shouldEmit = is_different(actual, predicted, mbg, treatment, cal, pump);
+ patientData = [actual, predicted, mbg, treatment, profile, cal, pump];
console.log('patientData', patientData.length);
if (shouldEmit) {
emitData( );
diff --git a/server.js b/server.js
index ef3dc75..95bb292 100644
--- a/server.js
+++ b/server.js
@@ -38,6 +38,7 @@ var store = require('./lib/storage')(env, function() {
console.info("Mongo ready");
entries.ensureIndexes(env.mongo_collection, store);
treatments.ensureIndexes(env.treatments_collection, store);
+ //pumphistory.ensureIndexes(env.pumphistory_collection, store);
devicestatus.ensureIndexes(env.devicestatus_collection, store);
});
@@ -52,7 +53,8 @@ var settings = require('./lib/settings')(env.settings_collection, store);
var treatmentsStorage = treatments.storage(env.treatments_collection, store, pushover);
var profile = require('./lib/profile')(env.profile_collection, store);
var devicestatusStorage = devicestatus.storage(env.devicestatus_collection, store);
-var api = require('./lib/api/')(env, entriesStorage, settings, treatmentsStorage, profile, devicestatusStorage);
+var pumphistory = require('./lib/pumphistory')(env.pumphistory_collection, store);
+var api = require('./lib/api/')(env, entriesStorage, settings, treatmentsStorage, profile, devicestatusStorage, pumphistory);
var pebble = require('./lib/pebble');
///////////////////////////////////////////////////
@@ -106,7 +108,7 @@ store(function ready ( ) {
// setup socket io for data and message transmission
///////////////////////////////////////////////////
var websocket = require('./lib/websocket');
- var io = websocket(env, server, entriesStorage, treatmentsStorage, profile);
+ var io = websocket(env, server, entriesStorage, treatmentsStorage, profile, pumphistory);
});
///////////////////////////////////////////////////
diff --git a/static/js/client.js b/static/js/client.js
index 567fbb4..1e82c99 100644
--- a/static/js/client.js
+++ b/static/js/client.js
@@ -32,6 +32,8 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
, treatments
, profile
, cal
+ , pumpHistory
+ , tempTreatments
, padding = { top: 20, right: 10, bottom: 30, left: 10 }
, opacity = {current: 1, DAY: 1, NIGHT: 0.5}
, now = Date.now()
@@ -1106,24 +1108,35 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
var CR = treatment.CR || 20;
var carbs = treatment.carbs || CR;
- var insulin = treatment.insulin || 1;
+ var insulin = Math.abs(treatment.insulin) || 1;
- var R1 = Math.sqrt(Math.min(carbs, insulin * CR)) / scale,
- R2 = Math.sqrt(Math.max(carbs, insulin * CR)) / scale,
- R3 = R2 + 8 / scale;
+ var R1 = Math.sqrt(Math.min(carbs, insulin * CR)+4) / scale;
+ var R2 = Math.sqrt(Math.max(carbs, insulin * CR)+4) / scale;
+ var R3 = R2 + 10 / scale;
+ var rWhite = 0, rBlue = 0;
+ if (treatment.carbs) { rWhite = R1; }
+ if (treatment.insulin < 0) { rWhite = R1; }
+ if (treatment.insulin > 0) { rBlue = R1; }
var arc_data = [
- { 'element': '', 'color': 'white', 'start': -1.5708, 'end': 1.5708, 'inner': 0, 'outer': R1 },
+ { 'element': '', 'color': 'magenta', 'start': -1.5708, 'end': 1.5708, 'inner': 0, 'outer': rWhite },
{ 'element': '', 'color': 'transparent', 'start': -1.5708, 'end': 1.5708, 'inner': R2, 'outer': R3 },
- { 'element': '', 'color': '#0099ff', 'start': 1.5708, 'end': 4.7124, 'inner': 0, 'outer': R1 },
+ { 'element': '', 'color': '#0099ff', 'start': 1.5708, 'end': 4.7124, 'inner': 0, 'outer': rBlue },
{ 'element': '', 'color': 'transparent', 'start': 1.5708, 'end': 4.7124, 'inner': R2, 'outer': R3 }
];
arc_data[0].outlineOnly = !treatment.carbs;
arc_data[2].outlineOnly = !treatment.insulin;
+ // negative boluses should be magenta like carbs
+ if (treatment.insulin < 0) {
+ arc_data[0].outlineOnly = false;
+ arc_data[2].outlineOnly = true;
+ }
+
if (treatment.carbs > 0) arc_data[1].element = Math.round(treatment.carbs) + ' g';
- if (treatment.insulin > 0) arc_data[3].element = Math.round(treatment.insulin * 100) / 100 + ' U';
+ if (treatment.insulin < -0.1) arc_data[1].element = Math.round(treatment.insulin * 100) / 100 + ' U';
+ if (treatment.insulin > 0.1) arc_data[3].element = Math.round(treatment.insulin * 100) / 100 + ' U';
var arc = d3.svg.arc()
.innerRadius(function (d) { return 5 * d.inner; })
@@ -1163,11 +1176,13 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
// labels for carbs and insulin
+ var labelColor = 'magenta';
+ if (rWhite == 0 && rBlue > 0) { labelColor = '#0099ff'; }
if (showValues) {
var label = treatmentDots.append('g')
.attr('class', 'path')
.attr('id', 'label')
- .style('fill', 'white');
+ .style('fill', labelColor);
label.append('text')
.style('font-size', 30 / scale)
.style('font-family', 'Arial')
@@ -1383,12 +1398,65 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
if (tIOB && tIOB.activityContrib) activity += tIOB.activityContrib;
}
});
+
return {
iob: iob,
activity: activity
};
}
+ function calcTempTreatments() {
+ var tempHistory = [];
+ for (var i=0; i < pumpHistory.length; i++) {
+ //if(pumpHistory[i].date < time) {
+ if (pumpHistory[i]._type == "TempBasal") {
+ var rate = pumpHistory[i].rate;
+ var date = pumpHistory[i].date;
+ if (i>0 && pumpHistory[i-1].date == date && pumpHistory[i-1]._type == "TempBasalDuration") {
+ var duration = pumpHistory[i-1]['duration (min)'];
+ } else if (i+1<pumpHistory.length && pumpHistory[i+1].date == date && pumpHistory[i+1]._type == "TempBasalDuration") {
+ var duration = pumpHistory[i+1]['duration (min)'];
+ } else { console.log("No duration found for "+rate+" U/hr basal"+date); }
+ var temp = {};
+ temp.rate = rate;
+ temp.date = date;
+ temp.started_at = new Date(temp.date);
+ temp.duration = duration;
+ tempHistory.push(temp);
+ }
+ //}
+ };
+ for (var i=0; i+1 < tempHistory.length; i++) {
+ if (tempHistory[i].date + tempHistory[i].duration*60*1000 > tempHistory[i+1].date) {
+ tempHistory[i].duration = (tempHistory[i+1].date - tempHistory[i].date)/60/1000;
+ }
+ }
+ var tempBoluses = [];
+ var tempBolusSize;
+ for (var i=0; i < tempHistory.length; i++) {
+ if (tempHistory[i].duration > 0) {
+ var netBasalRate = tempHistory[i].rate-profile.basal;
+ if (netBasalRate < 0) { tempBolusSize = -0.1; }
+ else { tempBolusSize = 0.1; }
+ var netBasalAmount = Math.round(netBasalRate*tempHistory[i].duration*10/6)/100
+ var tempBolusCount = Math.round(netBasalAmount / tempBolusSize);
+ var tempBolusSpacing = tempHistory[i].duration / tempBolusCount;
+ for (var j=0; j < tempBolusCount; j++) {
+ var tempBolus = {};
+ tempBolus.insulin = tempBolusSize;
+ tempBolus.date = tempHistory[i].date + j * tempBolusSpacing*60*1000;
+ tempBolus.created_at = new Date(tempBolus.date);
+ tempBoluses.push(tempBolus);
+ }
+ }
+ }
+ return {
+ tempBoluses: tempBoluses,
+ tempHistory: tempHistory
+ };
+
+ }
+
function cobTotal(treatments, time) {
var liverSensRatio = 1;
var sens = profile.sens;
@@ -1447,7 +1515,7 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
function carbImpact(rawCarbImpact, insulinImpact) {
var liverSensRatio = 1.0;
var liverCarbImpactMax = 0.7;
- var liverCarbImpact = Math.min(liverCarbImpactMax, liverSensRatio*insulinImpact);
+ var liverCarbImpact = Math.max(0,Math.min(liverCarbImpactMax, liverSensRatio*insulinImpact));
//var liverCarbImpact = liverSensRatio*insulinImpact;
var netCarbImpact = Math.max(0, rawCarbImpact-liverCarbImpact);
var totalImpact = netCarbImpact - insulinImpact;
@@ -1696,6 +1764,10 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage;
profile = d[4][0];
cal = d[5][d[5].length-1];
+ pumpHistory = d[6];
+ tempTreatments = calcTempTreatments().tempBoluses;
+ treatments = treatments.concat(tempTreatments);
+
var temp1 = [ ];
if (cal && showRawBGs()) {
temp1 = d[0].map(function (entry) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment