Bolus settings (#6834)

* Add bolus plugin and restructure rendering settings

* Add setting to prevent automated micro boluses from triggering notifications and snoozing alarms

* clean up

* Small change to the bolus-settings branch so it supports flexible configuration that enables the old behavior

* Translations

* Fix settings default

Co-authored-by: Jason Calabrese <jason@cbrese.com>
This commit is contained in:
Sulka Haro
2021-02-02 19:14:32 +02:00
committed by GitHub
co-authored by Jason Calabrese
parent 84ac8f7e74
commit d762694b83
10 changed files with 125 additions and 32 deletions
+10 -2
View File
@@ -104,6 +104,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md)
- [`bage` (Battery Age)](#bage-battery-age)
- [`treatmentnotify` (Treatment Notifications)](#treatmentnotify-treatment-notifications)
- [`basal` (Basal Profile)](#basal-basal-profile)
- [`bolus` (Bolus Rendering)](#bolus-bolus-rendering)
- [`bridge` (Share2Nightscout bridge)](#bridge-share2nightscout-bridge)
- [`mmconnect` (MiniMed Connect bridge)](#mmconnect-minimed-connect-bridge)
- [`pump` (Pump Monitoring)](#pump-pump-monitoring)
@@ -313,7 +314,6 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or
* The `linear` option has equidistant tick marks; the range used is dynamic so that space at the top of chart isn't wasted.
* The `log-dynamic` is similar to the default `log` options, but uses the same dynamic range and the `linear` scale.
* `EDIT_MODE` (`on`) - possible values `on` or `off`. Enables the icon allowing for editing of treatments in the main view.
* `BOLUS_RENDER_OVER` (1) - U value over which the bolus values are rendered on the chart if the 'x U and Over' option is selected. This value can be an integer or a float, e.g. 0.3, 1.5, 2, etc...
### Predefined values for your server settings (optional)
* `INSECURE_USE_HTTP` (`false`) - Redirect unsafe http traffic to https. Possible values `false`, or `true`. Your site redirects to `https` by default. If you don't want that from Nightscout, but want to implement that with a Nginx or Apache proxy, set `INSECURE_USE_HTTP` to `true`. Note: This will allow (unsafe) http traffic to your Nightscout instance and is not recommended.
@@ -470,12 +470,20 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or
* `BAGE_URGENT` (`360`) - If time since last `Pump Battery Change` matches `BAGE_URGENT` hours, user will be issued a persistent warning of overdue change (default of 360 hours is 15 days).
##### `treatmentnotify` (Treatment Notifications)
Generates notifications when a treatment has been entered and snoozes alarms minutes after a treatment. Default snooze is 10 minutes, and can be set using the `TREATMENTNOTIFY_SNOOZE_MINS` [extended setting](#extended-settings).
Generates notifications when a treatment has been entered and snoozes alarms minutes after a treatment.
* `TREATMENTNOTIFY_SNOOZE_MINS` (`10`) - Number of minutes to snooze notifications after a treatment is entered
* `TREATMENTNOTIFY_INCLUDE_BOLUSES_OVER` (`0`) - U value over which the bolus will trigger a notification and snooze alarms
##### `basal` (Basal Profile)
Adds the Basal pill visualization to display the basal rate for the current time. Also enables the `bwp` plugin to calculate correction temp basal suggestions. Uses the `basal` field from the [treatment profile](#treatment-profile). Also uses the extended setting:
* `BASAL_RENDER` (`none`) - Possible values are `none`, `default`, or `icicle` (inverted)
##### `bolus` (Bolus Rendering)
Settings to configure Bolus rendering
* `BOLUS_RENDER_OVER` (`0`) - U value over which the bolus labels use the format defined in `BOLUS_RENDER_FORMAT`. This value can be an integer or a float, e.g. 0.3, 1.5, 2, etc.
* `BOLUS_RENDER_FORMAT` (`default`) - Possible values are `hidden`, `default` (with leading zero and U), `concise` (with U, without leading zero), and `minimal` (without leading zero and U).
* `BOLUS_RENDER_FORMAT_SMALL` (`default`) - Possible values are `hidden`, `default` (with leading zero and U), `concise` (with U, without leading zero), and `minimal` (without leading zero and U).
##### `bridge` (Share2Nightscout bridge)
Glucose reading directly from the Dexcom Share service, uses these extended settings:
* `BRIDGE_USER_NAME` - Your username for the Share service.
+39 -6
View File
@@ -13,6 +13,29 @@ function init (client, serverSettings, $) {
var storage = Storages.localStorage;
var settings = require('../settings')();
function updateBolusRender () {
var bolusSettings = client.settings.extendedSettings.bolus || {};
var allRenderOverOptions = [5, 1, 0.5, 0.1];
if (_.isNumber(bolusSettings.renderOver) && bolusSettings.renderOver > 0 && bolusSettings.renderOver < Number.MAX_SAFE_INTEGER) {
allRenderOverOptions.push(_.toNumber(bolusSettings.renderOver));
}
var sortedRenderOverOptions = _.chain(allRenderOverOptions).uniq().sort().reverse().value();
_.forEach(sortedRenderOverOptions, function (optionValue) {
$('#bolusRenderOver').append(
$('<option></option>')
.attr('value', optionValue)
.text(client.translate('%1 U and Over', { params: [optionValue] }))
);
});
$('#bolusRenderOver').val(String(bolusSettings.renderOver || 0.5));
$('#bolusRenderFormat').val(bolusSettings.renderFormat ? bolusSettings.renderFormat : 'default');
$('#bolusRenderFormatSmall').val(bolusSettings.renderFormatSmall ? bolusSettings.renderFormatSmall : 'default');
}
function loadForm () {
var utils = client.utils;
var language = client.language;
@@ -70,7 +93,7 @@ function init (client, serverSettings, $) {
$('#basalrender').val(settings.extendedSettings.basal ? settings.extendedSettings.basal.render : 'none');
$('#bolusrender').val(settings.extendedSettings.bolus ? settings.extendedSettings.bolus.render : 'all');
updateBolusRender();
if (settings.timeFormat === 24) {
$('#24-browser').prop('checked', true);
@@ -162,7 +185,7 @@ function init (client, serverSettings, $) {
storage.remove(name);
});
storage.remove('basalrender');
storage.remove('bolusrender');
storage.remove('bolus');
event.preventDefault();
client.browserUtils.reload();
});
@@ -215,7 +238,11 @@ function init (client, serverSettings, $) {
, language: $('#language').val()
, scaleY: $('#scaleY').val()
, basalrender: $('#basalrender').val()
, bolusrender: $('#bolusrender').val()
, bolus: {
renderOver: $('#bolusRenderOver').val()
, renderFormat: $('#bolusRenderFormat').val()
, renderFormatSmall: $('#bolusRenderFormatSmall').val()
}
, showPlugins: checkedPluginNames()
, storageVersion: STORAGE_VERSION
});
@@ -276,11 +303,17 @@ function init (client, serverSettings, $) {
settings.extendedSettings.basal.render = basalStored !== null ? basalStored : settings.extendedSettings.basal.render;
if (!settings.extendedSettings.bolus) {
settings.extendedSettings.bolus = {};
settings.extendedSettings.bolus = {
renderOver: 0
, renderFormat: 'default'
, renderFormatSmall: 'default'
};
}
var bolusStored = storage.get('bolusrender');
settings.extendedSettings.bolus.render = bolusStored !== null ? bolusStored : settings.extendedSettings.bolus.render;
var bolusStored = storage.get('bolus');
settings.extendedSettings.bolus.renderOver = bolusStored !== null ? _.toNumber(bolusStored.renderOver) : settings.extendedSettings.bolus.renderOver;
settings.extendedSettings.bolus.renderFormat = bolusStored !== null ? bolusStored.renderFormat : settings.extendedSettings.bolus.renderFormat;
settings.extendedSettings.bolus.renderFormatSmall = bolusStored !== null ? bolusStored.renderFormatSmall : settings.extendedSettings.bolus.renderFormatSmall;
} catch (err) {
console.error(err);
-6
View File
@@ -445,11 +445,6 @@ client.load = function load (serverSettings, callback) {
}
}
function updateBolusRenderOver () {
var bolusRenderOver = (client.settings.bolusRenderOver || 1) + ' U and Over';
$('#bolusRenderOver').text(bolusRenderOver);
}
function alarmingNow () {
return container.hasClass('alarming');
}
@@ -1305,7 +1300,6 @@ client.load = function load (serverSettings, callback) {
prepareEntries();
updateTitle();
updateBolusRenderOver();
// Don't invoke D3 in headless mode
+16 -9
View File
@@ -529,7 +529,7 @@ function init (client, d3) {
};
}
function prepareArc (treatment, radius, renderBasal) {
function prepareArc (treatment, radius, bolusSettings) {
var arc_data = [
// white carb half-circle on top
{ 'element': '', 'color': 'white', 'start': -1.5708, 'end': 1.5708, 'inner': 0, 'outer': radius.R1 }
@@ -566,12 +566,14 @@ function init (client, d3) {
if (treatment.insulin > 0) {
var dosage_units = '' + Math.round(treatment.insulin * 100) / 100;
var format = treatment.insulin < bolusSettings.renderOver ? bolusSettings.renderFormatSmall : bolusSettings.renderFormat;
if (renderBasal === 'all-remove-zero-u') {
if (_.includes(['concise', 'minimal'], format)) {
dosage_units = (dosage_units + "").replace(/^0/, "");
}
var unit_of_measurement = (renderBasal === 'all-remove-zero-u' ? '' : ' U'); // One international unit of insulin (1 IU) is shown as '1 U'
var unit_of_measurement = (format === 'minimal' ? '' : ' U'); // One international unit of insulin (1 IU) is shown as '1 U'
arc_data[3].element = dosage_units + unit_of_measurement;
}
@@ -992,7 +994,8 @@ function init (client, d3) {
renderer.drawTreatments = function drawTreatments (client) {
var treatmentCount = 0;
var renderBasal = client.settings.extendedSettings.bolus.render;
var bolusSettings = client.settings.extendedSettings.bolus || {};
chart().focus.selectAll('.draggable-treatment').remove();
_.forEach(client.ddata.treatments, function eachTreatment (d) {
@@ -1001,17 +1004,21 @@ function init (client, d3) {
// add treatment bubbles
_.forEach(client.ddata.treatments, function eachTreatment (d) {
var showLabels = ( !d.carbs && ( ( renderBasal == 'none') || ( renderBasal === 'over' && d.insulin < client.settings.bolusRenderOver) ) ) ? false : true;
var showLabels = d.carbs || d.insulin;
if (d.insulin && d.insulin < bolusSettings.renderOver && bolusSettings.renderFormatSmall == 'hidden') {
showLabels = false;
}
renderer.drawTreatment(d, {
scale: renderer.bubbleScale()
, showLabels: showLabels
, treatments: treatmentCount
}, client.sbx.data.profile.getCarbRatio(new Date()),
renderBasal);
}
, client.sbx.data.profile.getCarbRatio(new Date())
, bolusSettings);
});
};
renderer.drawTreatment = function drawTreatment (treatment, opts, carbratio, renderBasal) {
renderer.drawTreatment = function drawTreatment (treatment, opts, carbratio, bolusSettings) {
if (!treatment.carbs && !treatment.protein && !treatment.fat && !treatment.insulin) {
return;
}
@@ -1029,7 +1036,7 @@ function init (client, d3) {
return;
}
var arc = prepareArc(treatment, radius, renderBasal);
var arc = prepareArc(treatment, radius, bolusSettings);
var treatmentDots = appendTreatments(treatment, arc);
appendLabels(treatmentDots, arc, opts);
};
+22
View File
@@ -0,0 +1,22 @@
'use strict';
function init () {
var bolus = {
name: 'bolus'
, label: 'Bolus'
, pluginType: 'fake'
};
bolus.getPrefs = function getPrefs(sbx) {
return {
renderFormat: sbx.extendedSettings.renderFormat ? sbx.extendedSettings.renderFormat : 'default'
, renderOver: sbx.extendedSettings.renderOver ? sbx.extendedSettings.renderOver : 0
, notifyOver: sbx.extendedSettings.notifyOver ? sbx.extendedSettings.notifyOver : 0
};
};
return bolus;
}
module.exports = init;
+2 -1
View File
@@ -46,6 +46,7 @@ function init (ctx) {
, require('./insulinage')(ctx)
, require('./batteryage')(ctx)
, require('./basalprofile')(ctx)
, require('./bolus')(ctx) // fake plugin to hold extended settings
, require('./boluscalc')(ctx) // fake plugin to show/hide
, require('./profile')(ctx) // fake plugin to hold extended settings
, require('./speech')(ctx)
@@ -128,7 +129,7 @@ function init (ctx) {
};
//these plugins are either always on or have custom settings
plugins.specialPlugins = 'ar2 bgnow delta direction timeago upbat rawbg errorcodes profile';
plugins.specialPlugins = 'ar2 bgnow delta direction timeago upbat rawbg errorcodes profile bolus';
plugins.shownPlugins = function(sbx) {
return _filter(enabledPlugins, function filterPlugins (plugin) {
+5
View File
@@ -20,12 +20,17 @@ function init(ctx) {
function filterTreatments (sbx) {
var treatments = sbx.data.treatments;
var includeBolusesOver = sbx.extendedSettings.includeBolusesOver || 0;
treatments = _.filter(treatments, function notOpenAPS (treatment) {
var ok = true;
var enteredBy = treatment.enteredBy;
if (enteredBy && (enteredBy.indexOf('openaps://') === 0 || enteredBy.indexOf('loop://') === 0)) {
ok = _.indexOf(MANUAL_TREATMENTS, treatment.eventType) >= 0;
}
if (ok && _.isNumber(treatment.insulin) && _.includes(['Meal Bolus', 'Correction Bolus'], treatment.eventType)) {
ok = treatment.insulin >= includeBolusesOver;
}
return ok;
});
+1 -2
View File
@@ -52,7 +52,6 @@ function init () {
, deNormalizeDates: false
, showClockDelta: false
, showClockLastTime: false
, bolusRenderOver: 1
, frameUrl1: ''
, frameUrl2: ''
, frameUrl3: ''
@@ -170,7 +169,7 @@ function init () {
}
//TODO: getting sent in status.json, shouldn't be
settings.DEFAULT_FEATURES = ['bgnow', 'delta', 'direction', 'timeago', 'devicestatus', 'upbat', 'errorcodes', 'profile', 'dbsize', 'runtimestate', 'basal', 'careportal'];
settings.DEFAULT_FEATURES = ['bgnow', 'delta', 'direction', 'timeago', 'devicestatus', 'upbat', 'errorcodes', 'profile', 'bolus', 'dbsize', 'runtimestate', 'basal', 'careportal'];
var wasSet = [];
+7
View File
@@ -694,4 +694,11 @@
,"Weekly Distribution":"Weekly Distribution"
,"Failed authentication":"Failed authentication"
,"A device at IP address %1 attempted authenticating with Nightscout with wrong credentials. Check if you have an uploader setup with wrong API_SECRET or token?": "A device at IP address %1 attempted authenticating with Nightscout with wrong credentials. Check if you have an uploader setup with wrong API_SECRET or token?"
,"Default (with leading zero and U)":"Default (with leading zero and U)"
,"Concise (with U, without leading zero)":"Concise (with U, without leading zero)"
,"Minimal (without leading zero and U)":"Minimal (without leading zero and U)"
,"Small Bolus Display":"Small Bolus Display"
,"Large Bolus Display":"Large Bolus Display"
,"Bolus Display Threshold":"Bolus Display Threshold"
,"%1 U and Over":"%1 U and Over"
}
+23 -6
View File
@@ -217,13 +217,30 @@
</dd>
</dl>
<dl>
<dt class="translate">Render Bolus Amount</dt>
<dt class="translate">Bolus Display Threshold</dt>
<dd>
<select id="bolusrender">
<option class="translate" value="all">All</option>
<option class="translate" value="all-remove-zero-u">All (without leading zero and U)</option>
<option class="translate" id="bolusRenderOver" value="over">1 U and Over</option>
<option class="translate" value="none">None</option>
<select id="bolusRenderOver"></select>
</dd>
</dl>
<dl>
<dt class="translate">Small Bolus Display</dt>
<dd>
<select id="bolusRenderFormatSmall">
<option class="translate" value="hidden">Hidden</option>
<option class="translate" value="default">Default (with leading zero and U)</option>
<option class="translate" value="concise">Concise (with U, without leading zero)</option>
<option class="translate" value="minimal">Minimal (without leading zero and U)</option>
</select>
</dd>
</dl>
<dl>
<dt class="translate">Large Bolus Display</dt>
<dd>
<select id="bolusRenderFormat">
<option class="translate" value="hidden">Hidden</option>
<option class="translate" value="default">Default (with leading zero and U)</option>
<option class="translate" value="concise">Concise (with U, without leading zero)</option>
<option class="translate" value="minimal">Minimal (without leading zero and U)</option>
</select>
</dd>
</dl>