From 1b786faf8fce7f6e923f504547760d8eb574473b Mon Sep 17 00:00:00 2001 From: Jason Calabrese Date: Fri, 24 Apr 2020 16:17:49 -0700 Subject: [PATCH 1/3] Add bolus plugin and restructure rendering settings --- README.md | 7 +++++- lib/client/browser-settings.js | 44 +++++++++++++++++++++++++++++----- lib/client/index.js | 7 ------ lib/client/renderer.js | 20 +++++++++------- lib/plugins/bolus.js | 22 +++++++++++++++++ lib/plugins/index.js | 3 ++- lib/settings.js | 3 +-- views/index.html | 17 ++++++++----- 8 files changed, 91 insertions(+), 32 deletions(-) create mode 100644 lib/plugins/bolus.js diff --git a/README.md b/README.md index bd55ebf8094..116a6ee63e2 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ Community maintained fork of the - [`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) @@ -294,7 +295,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. @@ -439,6 +439,11 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or 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 rendered on the chart. This value can be an integer or a float, e.g. 0.3, 1.5, 2, etc... Use 0 to render All bolus labels, use `Number.MAX_SAFE_INTEGER` (9007199254740991) if you want None of the bolus labels to be rendered. + * `BOLUS_RENDER_FORMAT` (`default`) - Possible values are `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. diff --git a/lib/client/browser-settings.js b/lib/client/browser-settings.js index f45631f4b6f..0c4c274e094 100644 --- a/lib/client/browser-settings.js +++ b/lib/client/browser-settings.js @@ -13,6 +13,31 @@ function init (client, serverSettings, $) { var storage = Storages.localStorage; var settings = require('../settings')(); + function updateBolusRender () { + var bolusSettings = client.settings.extendedSettings.bolus || {}; + + var allRenderOverOptions = [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(); + + $('#bolusRenderOver').append(''); + + _.forEach(sortedRenderOverOptions, function (optionValue) { + $('#bolusRenderOver').append( + $('') + .attr('value', optionValue) + .text(client.translate('%1 U and Over', { params: [optionValue] })) + ); + }); + + $('#bolusRenderOver').append(''); + $('#bolusRenderOver').val(String(bolusSettings.renderOver || 0)); + $('#bolusRenderFormat').val(bolusSettings.renderFormat ? bolusSettings.renderFormat : 'default'); + + } + function loadForm () { var utils = client.utils; var language = require('../language')(); @@ -71,7 +96,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); @@ -163,7 +188,7 @@ function init (client, serverSettings, $) { storage.remove(name); }); storage.remove('basalrender'); - storage.remove('bolusrender'); + storage.remove('bolus'); event.preventDefault(); client.browserUtils.reload(); }); @@ -216,7 +241,10 @@ function init (client, serverSettings, $) { , language: $('#language').val() , scaleY: $('#scaleY').val() , basalrender: $('#basalrender').val() - , bolusrender: $('#bolusrender').val() + , bolus: { + renderOver: $('#bolusRenderOver').val() + , renderFormat: $('#bolusRenderFormat').val() + } , showPlugins: checkedPluginNames() , storageVersion: STORAGE_VERSION }); @@ -276,11 +304,15 @@ 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' + }; } - 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; } catch (err) { console.error(err); diff --git a/lib/client/index.js b/lib/client/index.js index 29dc9593ae8..5c611306d9f 100644 --- a/lib/client/index.js +++ b/lib/client/index.js @@ -399,12 +399,6 @@ client.load = function load (serverSettings, callback) { } } - function updateBolusRenderOver () { - var bolusRenderOver = (client.settings.bolusRenderOver || 1) + ' U and Over'; - $('#bolusRenderOver').text(bolusRenderOver); - console.log('here'); - } - function alarmingNow () { return container.hasClass('alarming'); } @@ -1246,7 +1240,6 @@ client.load = function load (serverSettings, callback) { prepareEntries(); updateTitle(); - updateBolusRenderOver(); // Don't invoke D3 in headless mode diff --git a/lib/client/renderer.js b/lib/client/renderer.js index 818ee6f41d0..24d97a305a6 100644 --- a/lib/client/renderer.js +++ b/lib/client/renderer.js @@ -531,7 +531,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 } @@ -569,11 +569,11 @@ function init (client, d3) { if (treatment.insulin > 0) { var dosage_units = '' + Math.round(treatment.insulin * 100) / 100; - if (renderBasal === 'all-remove-zero-u') { + if (_.includes(['concise', 'minimal'], bolusSettings.renderFormat)) { 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 = (bolusSettings.renderFormat === 'minimal' ? '' : ' U'); // One international unit of insulin (1 IU) is shown as '1 U' arc_data[3].element = dosage_units + unit_of_measurement; } @@ -994,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) { @@ -1003,17 +1004,18 @@ 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 > bolusSettings.renderOver; 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; } @@ -1031,7 +1033,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); }; diff --git a/lib/plugins/bolus.js b/lib/plugins/bolus.js new file mode 100644 index 00000000000..bc2f9a322b9 --- /dev/null +++ b/lib/plugins/bolus.js @@ -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; \ No newline at end of file diff --git a/lib/plugins/index.js b/lib/plugins/index.js index 5a6cb2822da..3347dd6116a 100644 --- a/lib/plugins/index.js +++ b/lib/plugins/index.js @@ -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) @@ -126,7 +127,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) { diff --git a/lib/settings.js b/lib/settings.js index 5a19ba6309c..29e46369a9b 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -51,7 +51,6 @@ function init () { , deNormalizeDates: false , showClockDelta: false , showClockLastTime: false - , bolusRenderOver: 1 , frameUrl1: '' , frameUrl2: '' , frameUrl3: '' @@ -168,7 +167,7 @@ function init () { } //TODO: getting sent in status.json, shouldn't be - settings.DEFAULT_FEATURES = ['bgnow', 'delta', 'direction', 'timeago', 'devicestatus', 'upbat', 'errorcodes', 'profile', 'dbsize']; + settings.DEFAULT_FEATURES = ['bgnow', 'delta', 'direction', 'timeago', 'devicestatus', 'upbat', 'errorcodes', 'profile', 'bolus', 'dbsize']; var wasSet = []; diff --git a/views/index.html b/views/index.html index 6ef0dc2cce6..98025efe9b8 100644 --- a/views/index.html +++ b/views/index.html @@ -216,13 +216,18 @@
-
Render Bolus Amount
+
Bolus Render Over
- +
+
+
+
Bolus Render Format
+
+
From fc3703e6e5ce787a52b9b24b85a9e490f8914d1e Mon Sep 17 00:00:00 2001 From: Jason Calabrese Date: Fri, 24 Apr 2020 16:46:06 -0700 Subject: [PATCH 2/3] Add setting to prevent automated micro boluses from triggering notifications and snoozing alarms --- README.md | 4 +++- lib/plugins/treatmentnotify.js | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 116a6ee63e2..d80e3d433e5 100644 --- a/README.md +++ b/README.md @@ -433,7 +433,9 @@ 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.25`) - 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: diff --git a/lib/plugins/treatmentnotify.js b/lib/plugins/treatmentnotify.js index abb47c78dae..c75e0497988 100644 --- a/lib/plugins/treatmentnotify.js +++ b/lib/plugins/treatmentnotify.js @@ -19,12 +19,17 @@ function init() { function filterTreatments (sbx) { var treatments = sbx.data.treatments; + var includeBolusesOver = sbx.extendedSettings.includeBolusesOver || 0.25; + 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; }); From 91e10389caf857afa28664dc3f96c7928ccf9e44 Mon Sep 17 00:00:00 2001 From: Jason Calabrese Date: Fri, 24 Apr 2020 16:18:29 -0700 Subject: [PATCH 3/3] clean up --- lib/client/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/client/index.js b/lib/client/index.js index 5c611306d9f..1b8e75fd3fa 100644 --- a/lib/client/index.js +++ b/lib/client/index.js @@ -409,7 +409,6 @@ client.load = function load (serverSettings, callback) { function brushed () { // Brush not initialized - console.log("brushed"); if (!chart.theBrush) { return; }