nightscout
Version:
Nightscout acts as a web-based CGM (Continuous Glucose Monitor) to allow multiple caregivers to remotely view a patients glucose data in realtime.
146 lines (119 loc) • 4.35 kB
JavaScript
;
var _ = require('lodash');
function init (ctx) {
var translate = ctx.language.translate;
var rawbg = {
name: 'rawbg'
, label: 'Raw BG'
, pluginType: 'bg-status'
, pillFlip: true
};
rawbg.getPrefs = function getPrefs (sbx) {
return {
display: (sbx && sbx.extendedSettings.display) ? sbx.extendedSettings.display : 'unsmoothed'
};
};
rawbg.setProperties = function setProperties (sbx) {
sbx.offerProperty('rawbg', function setRawBG ( ) {
var result = { };
var currentSGV = sbx.lastSGVEntry();
//TODO:OnlyOneCal - currently we only load the last cal, so we can't ignore future data
var currentCal = _.last(sbx.data.cals);
var staleAndInRetroMode = sbx.data.inRetroMode && !sbx.isCurrent(currentSGV);
if (!staleAndInRetroMode && currentSGV && currentCal) {
result.mgdl = rawbg.calc(currentSGV, currentCal, sbx);
result.noiseLabel = rawbg.noiseCodeToDisplay(currentSGV.mgdl, currentSGV.noise);
result.sgv = currentSGV;
result.cal = currentCal;
result.displayLine = ['Raw BG:', sbx.scaleMgdl(result.mgdl), sbx.unitsLabel, result.noiseLabel].join(' ');
}
return result;
});
};
rawbg.updateVisualisation = function updateVisualisation (sbx) {
var prop = sbx.properties.rawbg;
var options = prop && prop.sgv && rawbg.showRawBGs(prop.sgv.mgdl, prop.sgv.noise, prop.cal, sbx) ? {
hide: !prop || !prop.mgdl
, value: sbx.scaleMgdl(prop.mgdl)
, label: prop.noiseLabel
} : {
hide: true
};
sbx.pluginBase.updatePillText(rawbg, options);
};
rawbg.calc = function calc(sgv, cal, sbx) {
var raw = 0;
var cleaned = cleanValues(sgv, cal);
var prefs = rawbg.getPrefs(sbx);
if (cleaned.slope === 0 || cleaned.unfiltered === 0 || cleaned.scale === 0) {
raw = 0;
} else if (cleaned.filtered === 0 || sgv.mgdl < 40 || prefs.display === 'unfiltered') {
raw = cleaned.scale * (cleaned.unfiltered - cleaned.intercept) / cleaned.slope;
} else if (prefs.display === 'filtered') {
raw = cleaned.scale * (cleaned.filtered - cleaned.intercept) / cleaned.slope;
} else {
var ratio = cleaned.scale * (cleaned.filtered - cleaned.intercept) / cleaned.slope / sgv.mgdl;
raw = cleaned.scale * (cleaned.unfiltered - cleaned.intercept) / cleaned.slope / ratio;
}
return Math.round(raw);
};
rawbg.isEnabled = function isEnabled(sbx) {
return sbx.settings.isEnabled('rawbg');
};
rawbg.showRawBGs = function showRawBGs(mgdl, noise, cal, sbx) {
return cal
&& rawbg.isEnabled(sbx)
&& (sbx.settings.showRawbg === 'always'
|| (sbx.settings.showRawbg === 'noise' && (noise >= 2 || mgdl < 40))
);
};
rawbg.noiseCodeToDisplay = function noiseCodeToDisplay(mgdl, noise) {
var display;
switch (parseInt(noise)) {
case 0: display = '---'; break;
case 1: display = translate('Clean'); break;
case 2: display = translate('Light'); break;
case 3: display = translate('Medium'); break;
case 4: display = translate('Heavy'); break;
default:
if (mgdl < 40) {
display = translate('Heavy');
} else {
display = '~~~';
}
break;
}
return display;
};
function virtAsstRawBGHandler (next, slots, sbx) {
var rawBg = _.get(sbx, 'properties.rawbg.mgdl');
if (rawBg) {
var response = translate('virtAsstRawBG', {
params: [
rawBg
]
});
next(translate('virtAsstTitleRawBG'), response);
} else {
next(translate('virtAsstTitleRawBG'), translate('virtAsstUnknown'));
}
}
rawbg.virtAsst = {
intentHandlers: [{
intent: 'MetricNow'
, metrics:['raw bg', 'raw blood glucose']
, intentHandler: virtAsstRawBGHandler
}]
};
return rawbg;
}
function cleanValues (sgv, cal) {
return {
unfiltered: parseInt(sgv.unfiltered) || 0
, filtered: parseInt(sgv.filtered) || 0
, scale: parseFloat(cal.scale) || 0
, intercept: parseFloat(cal.intercept) || 0
, slope: parseFloat(cal.slope) || 0
};
}
module.exports = init;