|
|
@@ -1,3 +1,5 @@ |
|
|
+'use strict';
|
|
|
+
|
|
|
var DIRECTIONS = {
|
|
|
NONE: 0
|
|
|
, DoubleUp: 1
|
|
|
@@ -12,6 +14,7 @@ var DIRECTIONS = { |
|
|
};
|
|
|
|
|
|
var iob = require("./iob")();
|
|
|
+var async = require('async');
|
|
|
|
|
|
function directionToTrend (direction) {
|
|
|
var trend = 8;
|
|
|
@@ -22,97 +25,125 @@ function directionToTrend (direction) { |
|
|
}
|
|
|
|
|
|
function pebble (req, res) {
|
|
|
- var ONE_DAY = 24 * 60 * 60 * 1000;
|
|
|
- var useMetricBg = (req.query.units === "mmol");
|
|
|
- var uploaderBattery;
|
|
|
- var treatmentResults;
|
|
|
- var profileResult;
|
|
|
+ var ONE_DAY = 24 * 60 * 60 * 1000
|
|
|
+ , uploaderBattery
|
|
|
+ , treatmentResults
|
|
|
+ , profileResult
|
|
|
+ , sgvData = [ ]
|
|
|
+ , calData = [ ];
|
|
|
|
|
|
function scaleBg(bg) {
|
|
|
- if (useMetricBg) {
|
|
|
+ if (req.mmol) {
|
|
|
return (Math.round((bg / 18) * 10) / 10).toFixed(1);
|
|
|
- } else
|
|
|
+ } else {
|
|
|
return bg;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- function get_latest (err, results) {
|
|
|
+ function sendData () {
|
|
|
var now = Date.now();
|
|
|
- var sgvData = [ ];
|
|
|
- var calData = [ ];
|
|
|
-
|
|
|
- results.forEach(function(element, index, array) {
|
|
|
- if (element) {
|
|
|
- var obj = {};
|
|
|
- if (element.sgv) {
|
|
|
- var next = null;
|
|
|
- var sgvs = results.filter(function(d) {
|
|
|
- return !!d.sgv;
|
|
|
- });
|
|
|
- if (index + 1 < sgvs.length) {
|
|
|
- next = sgvs[index + 1];
|
|
|
- }
|
|
|
- obj.sgv = scaleBg(element.sgv).toString();
|
|
|
- obj.bgdelta = (next ? (scaleBg(element.sgv) - scaleBg(next.sgv) ) : 0);
|
|
|
- if (useMetricBg) {
|
|
|
- obj.bgdelta = obj.bgdelta.toFixed(1);
|
|
|
- }
|
|
|
- if ('direction' in element) {
|
|
|
- obj.trend = directionToTrend(element.direction);
|
|
|
- obj.direction = element.direction;
|
|
|
- }
|
|
|
- obj.datetime = element.date;
|
|
|
- if (req.rawbg) {
|
|
|
- obj.filtered = element.filtered;
|
|
|
- obj.unfiltered = element.unfiltered;
|
|
|
- obj.noise = element.noise;
|
|
|
- obj.rssi = element.rssi;
|
|
|
- }
|
|
|
- // obj.date = element.date.toString( );
|
|
|
- sgvData.push(obj);
|
|
|
- } else if (req.rawbg && element.type == 'cal') {
|
|
|
- calData.push(element);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
|
|
|
- var count = parseInt(req.query.count) || 1;
|
|
|
-
|
|
|
- var bgs = sgvData.slice(0, count);
|
|
|
//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;
|
|
|
+ if (sgvData.length > 0) {
|
|
|
+ sgvData[0].battery = uploaderBattery ? "" + uploaderBattery : undefined;
|
|
|
+ if (req.iob) {
|
|
|
+ sgvData[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) };
|
|
|
+ var result = { status: [ {now: now} ], bgs: sgvData, cals: calData };
|
|
|
res.setHeader('content-type', 'application/json');
|
|
|
res.write(JSON.stringify(result));
|
|
|
res.end( );
|
|
|
- // collection.db.close();
|
|
|
}
|
|
|
- req.devicestatus.last(function(err, value) {
|
|
|
- if (!err && value) {
|
|
|
- uploaderBattery = value.uploaderBattery;
|
|
|
- } else {
|
|
|
- console.error("req.devicestatus.tail", err);
|
|
|
- }
|
|
|
|
|
|
- var earliest_data = Date.now() - ONE_DAY;
|
|
|
- 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 earliest_data = Date.now() - ONE_DAY;
|
|
|
+
|
|
|
+ async.parallel({
|
|
|
+ devicestatus: function (callback) {
|
|
|
+ req.devicestatus.last(function (err, value) {
|
|
|
+ if (!err && value) {
|
|
|
+ uploaderBattery = value.uploaderBattery;
|
|
|
+ } else {
|
|
|
+ console.error("req.devicestatus.tail", err);
|
|
|
}
|
|
|
- }
|
|
|
+ callback();
|
|
|
});
|
|
|
- var q = { find: {"date": {"$gte": earliest_data}} };
|
|
|
- req.entries.list(q, get_latest);
|
|
|
- });
|
|
|
- });
|
|
|
- });
|
|
|
+ }
|
|
|
+ , treatments: function(callback) {
|
|
|
+ loadTreatments(req, earliest_data, function (err, trs) {
|
|
|
+ treatmentResults = trs;
|
|
|
+ callback();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ , profile: function(callback) {
|
|
|
+ loadProfile(req, function (err, profileResults) {
|
|
|
+ profileResults.forEach(function (profile) {
|
|
|
+ if (profile) {
|
|
|
+ if (profile.dia) {
|
|
|
+ profileResult = profile;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ callback();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ , cal: function(callback) {
|
|
|
+ if (req.rawbg) {
|
|
|
+ var cq = { count: req.count, find: {type: 'cal'} };
|
|
|
+ req.entries.list(cq, function (err, results) {
|
|
|
+ results.forEach(function (element) {
|
|
|
+ if (element) {
|
|
|
+ calData.push({
|
|
|
+ slope: Math.round(element.slope)
|
|
|
+ , intercept: Math.round(element.intercept)
|
|
|
+ , scale: Math.round(element.scale)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ callback();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ , entries: function(callback) {
|
|
|
+ var q = { count: req.count, find: { "sgv": { $exists: true }} };
|
|
|
+
|
|
|
+ req.entries.list(q, function(err, results) {
|
|
|
+ results.forEach(function(element, index) {
|
|
|
+ if (element) {
|
|
|
+ var obj = {};
|
|
|
+ var next = null;
|
|
|
+ var sgvs = results.filter(function(d) {
|
|
|
+ return !!d.sgv;
|
|
|
+ });
|
|
|
+ if (index + 1 < sgvs.length) {
|
|
|
+ next = sgvs[index + 1];
|
|
|
+ }
|
|
|
+ obj.sgv = scaleBg(element.sgv).toString();
|
|
|
+ obj.bgdelta = (next ? (scaleBg(element.sgv) - scaleBg(next.sgv) ) : 0);
|
|
|
+ if (req.mmol) {
|
|
|
+ obj.bgdelta = obj.bgdelta.toFixed(1);
|
|
|
+ }
|
|
|
+ if ('direction' in element) {
|
|
|
+ obj.trend = directionToTrend(element.direction);
|
|
|
+ obj.direction = element.direction;
|
|
|
+ }
|
|
|
+ obj.datetime = element.date;
|
|
|
+ if (req.rawbg) {
|
|
|
+ obj.filtered = element.filtered;
|
|
|
+ obj.unfiltered = element.unfiltered;
|
|
|
+ obj.noise = element.noise;
|
|
|
+ }
|
|
|
+ sgvData.push(obj);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ callback();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, sendData);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
function loadTreatments(req, earliest_data, fn) {
|
|
|
@@ -140,6 +171,9 @@ function configure (entries, treatments, profile, devicestatus, env) { |
|
|
req.devicestatus = devicestatus;
|
|
|
req.rawbg = env.enable && env.enable.indexOf('rawbg') > -1;
|
|
|
req.iob = env.enable && env.enable.indexOf('iob') > -1;
|
|
|
+ req.mmol = (req.query.units || env.DISPLAY_UNITS) === 'mmol';
|
|
|
+ req.count = parseInt(req.query.count) || 1;
|
|
|
+
|
|
|
next( );
|
|
|
}
|
|
|
return [middle, pebble];
|
|
|
|