From 9007ab84fedfd580022ae5bc02633545abc8ded9 Mon Sep 17 00:00:00 2001 From: Michael Kroes Date: Sun, 12 Jan 2025 19:50:57 +0100 Subject: [PATCH] Fixed the OpenAPS pill and forecast lines from not showing when unexpected data is present in lastEnacted --- lib/plugins/openaps.js | 2 +- tests/data/missingRateOnLastEnacted.json | 117 +++++++++++++++++++++ tests/data/statusWithWorkingForecast.json | 121 ++++++++++++++++++++++ tests/openaps.missingPill.test.js | 63 +++++++++++ 4 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 tests/data/missingRateOnLastEnacted.json create mode 100644 tests/data/statusWithWorkingForecast.json create mode 100644 tests/openaps.missingPill.test.js diff --git a/lib/plugins/openaps.js b/lib/plugins/openaps.js index 3b3136a274b..4073fc7a9f8 100644 --- a/lib/plugins/openaps.js +++ b/lib/plugins/openaps.js @@ -488,7 +488,7 @@ function init (ctx) { var valueParts = [ valueString('BG: ', bg) , ', Temp Basal' + (canceled ? ' Canceled' : ' Started') + '' - , canceled ? '' : ' ' + prop.lastEnacted.rate.toFixed(2) + ' for ' + prop.lastEnacted.duration + 'm' + , canceled ? '' : ' ' + (prop.lastEnacted.rate ?? 0) + ' for ' + prop.lastEnacted.duration + 'm' , valueString(', ', prop.lastEnacted.reason) , prop.lastEnacted.mealAssist && _.includes(selectedFields, 'meal-assist') ? ' Meal Assist: ' + prop.lastEnacted.mealAssist : '' ]; diff --git a/tests/data/missingRateOnLastEnacted.json b/tests/data/missingRateOnLastEnacted.json new file mode 100644 index 00000000000..8da8a43a1a9 --- /dev/null +++ b/tests/data/missingRateOnLastEnacted.json @@ -0,0 +1,117 @@ +[ + { + "_id": {"$oid": "6783c443748bf2ff9a89c6a5"}, + "created_at": "2025-01-12T13:31:47.933Z", + "device": "Trio", + "openaps": { + "version": "0.7.1", + "iob": { + "iobWithZeroTemp": { + "time": "2025-01-12T13:31:41.557Z", + "activity": 0.025, + "netbasalinsulin": -1.35, + "bolusinsulin": 9.9, + "basaliob": -0.616, + "bolusiob": 4.035, + "iob": 3.42 + }, + "iob": 3.42, + "bolusiob": 4.035, + "lastTemp": { + "rate": 0, + "timestamp": "2025-01-12T13:26:49.693Z", + "started_at": "2025-01-12T13:26:49.693Z", + "duration": 5.86, + "date": 1736688409693 + }, + "time": "2025-01-12T13:31:41.557Z", + "basaliob": -0.616, + "netbasalinsulin": -1.35, + "lastBolusTime": 1736686907187, + "activity": 0.025, + "bolusinsulin": 9.9 + }, + "suggested": { + "sensitivityRatio": 1.4833613770052834, + "timestamp": "2025-01-12T13:31:45.550Z", + "temp": "absolute", + "reason": "Autosens ratio: 1.48, ISF: 4.5→3, COB: 0, Dev: 0.9, BGI: -0.4, CR: 8→5.4, Target: 5.5→4.8, minPredBG 2.7, minGuardBG 1.1, IOBpredBG 2.2, UAMpredBG 2.2, TDD: 31.1 U, 81% Bolus 19% Basal, Dynamic ISF/CR: On/On, Sigmoid function, AF: 0.7, Basal ratio: 1; minGuardBG 1.1<3.5 115m left and 0 ~ req 0U/hr: no temp required", + "insulinReq": 0, + "COB": 0, + "current_target": 86, + "manualBolusErrorString": 2, + "ISF": 3, + "reservoir": 170.2, + "expectedDelta": -4.7, + "threshold": 3.5, + "bg": 204, + "insulinForManualBolus": -0.86, + "minDelta": -4, + "eventualBG": 39, + "insulin": { + "temp_basal": 5.9, + "scheduled_basal": 0, + "TDD": 31.1, + "bolus": 25.2 + }, + "minGuardBG": 20, + "TDD": 31.1, + "deliverAt": "2025-01-12T13:31:45.550Z", + "IOB": 3.42 + }, + "enacted": { + "temp": "absolute", + "sensitivityRatio": 1.4833613770052834, + "TDD": 31.1, + "current_target": 86, + "insulinForManualBolus": -0.86, + "expectedDelta": -4.7, + "timestamp": "2025-01-12T13:31:47.779Z", + "bg": 204, + "recieved": true, + "reservoir": 170.2, + "insulin": { + "bolus": 25.2, + "TDD": 31.1, + "temp_basal": 5.9, + "scheduled_basal": 0 + }, + "manualBolusErrorString": 2, + "insulinReq": 0, + "predBGs": { + "IOB": [204, 200, 195, 190, 185, 180, 174, 169, 163, 157, 151, 145, 139, 133, 128, 122, 117, 112, 107, 102, 98, 93, 89, 85, 82, 78, 75, 72, 69, 66, 63, 61, 59, 56, 54, 52, 50, 48, 47, 45, 43, 42, 41, 39], + "UAM": [204, 198, 191, 184, 177, 170, 164, 157, 150, 144, 137, 131, 125, 119, 113, 108, 103, 97, 93, 88, 83, 79, 75, 71, 67, 64, 61, 58, 55, 52, 49, 47, 44, 42, 40, 39], + "ZT": [204, 197, 190, 183, 176, 170, 163, 156, 150, 144, 138, 132, 127, 121, 116, 112, 107, 103, 99, 95, 92, 89, 86, 84, 82, 80, 78, 77, 75, 74, 73, 73, 72, 72, 72, 72, 72, 72, 73, 74, 74, 75, 76, 77, 79, 80, 82, 83] + }, + "ISF": 3, + "reason": "Autosens ratio: 1.48, ISF: 4.5→3, COB: 0, Dev: 0.9, BGI: -0.4, CR: 8→5.4, Target: 5.5→4.8, minPredBG 2.7, minGuardBG 1.1, IOBpredBG 2.2, UAMpredBG 2.2, TDD: 31.1 U, 81% Bolus 19% Basal, Dynamic ISF/CR: On/On, Sigmoid function, AF: 0.7, Basal ratio: 1; minGuardBG 1.1<3.5 115m left and 0 ~ req 0U/hr: no temp required", + "IOB": 3.42, + "COB": 0, + "deliverAt": "2025-01-12T13:31:45.550Z", + "eventualBG": 39, + "minDelta": -4, + "minGuardBG": 20, + "threshold": 3.5 + } + }, + "pump": { + "battery": { + "display": true, + "percent": 100, + "string": "normal" + }, + "reservoir": 170.2, + "status": { + "status": "normal", + "bolusing": false, + "suspended": false, + "timestamp": "2025-01-12T13:26:49.736Z" + }, + "clock": "2025-01-12T13:31:47.884Z" + }, + "uploader": { + "battery": 100 + }, + "utcOffset": 60 + } +] \ No newline at end of file diff --git a/tests/data/statusWithWorkingForecast.json b/tests/data/statusWithWorkingForecast.json new file mode 100644 index 00000000000..7f93e3d4dea --- /dev/null +++ b/tests/data/statusWithWorkingForecast.json @@ -0,0 +1,121 @@ +[ + { + "_id": {"$oid": "6783c31d748bf2ff9a89c6a3"}, + "created_at": "2025-01-12T13:26:53.937Z", + "device": "Trio", + "openaps": { + "iob": { + "bolusiob": 4.184, + "lastTemp": { + "rate": 0, + "timestamp": "2025-01-12T13:11:46.761Z", + "started_at": "2025-01-12T13:11:46.761Z", + "date": 1736687506761, + "duration": 15.84 + }, + "lastBolusTime": 1736686907187, + "basaliob": -0.59, + "netbasalinsulin": -1.3, + "bolusinsulin": 9.9, + "time": "2025-01-12T13:26:37.086Z", + "activity": 0.0245, + "iob": 3.594, + "iobWithZeroTemp": { + "basaliob": -0.59, + "bolusinsulin": 9.9, + "activity": 0.0245, + "iob": 3.594, + "netbasalinsulin": -1.3, + "bolusiob": 4.184, + "time": "2025-01-12T13:26:37.086Z" + } + }, + "version": "0.7.1", + "suggested": { + "temp": "absolute", + "expectedDelta": -5, + "reservoir": 170.2, + "reason": "Autosens ratio: 1.49, ISF: 4.5→3, COB: 0, Dev: 1.9, BGI: -0.4, CR: 8→5.4, Target: 5.5→4.8, minPredBG 2.7, minGuardBG 1.2, IOBpredBG 2.6, UAMpredBG 2.2, TDD: 31.2 U, 81% Bolus 19% Basal, Dynamic ISF/CR: On/On, Sigmoid function, AF: 0.7, Basal ratio: 1; minGuardBG 1.2<3.5", + "deliverAt": "2025-01-12T13:26:45.570Z", + "insulin": { + "scheduled_basal": 0, + "temp_basal": 5.9, + "TDD": 31.2, + "bolus": 25.3 + }, + "sensitivityRatio": 1.485721936996895, + "duration": 120, + "IOB": 3.594, + "minDelta": -1, + "timestamp": "2025-01-12T13:26:45.570Z", + "eventualBG": 46, + "ISF": 3, + "TDD": 31.2, + "threshold": 3.5, + "COB": 0, + "bg": 208, + "insulinReq": 0, + "manualBolusErrorString": 2, + "current_target": 86, + "insulinForManualBolus": -0.73, + "minGuardBG": 22, + "rate": 0 + }, + "enacted": { + "reason": "Autosens ratio: 1.49, ISF: 4.5→3, COB: 0, Dev: 1.9, BGI: -0.4, CR: 8→5.4, Target: 5.5→4.8, minPredBG 2.7, minGuardBG 1.2, IOBpredBG 2.6, UAMpredBG 2.2, TDD: 31.2 U, 81% Bolus 19% Basal, Dynamic ISF/CR: On/On, Sigmoid function, AF: 0.7, Basal ratio: 1; minGuardBG 1.2<3.5", + "minDelta": -1, + "TDD": 31.2, + "eventualBG": 46, + "threshold": 3.5, + "temp": "absolute", + "manualBolusErrorString": 2, + "bg": 208, + "IOB": 3.594, + "current_target": 86, + "recieved": true, + "predBGs": { + "ZT": [208, 201, 195, 188, 181, 174, 167, 160, 154, 147, 141, 135, 130, 124, 119, 114, 109, 105, 101, 97, 93, 90, 87, 85, 82, 80, 78, 77, 75, 74, 73, 72, 72, 71, 71, 71, 71, 71, 72, 72, 73, 74, 75, 76, 77, 78, 80, 81], + "UAM": [208, 205, 201, 195, 188, 181, 174, 167, 160, 153, 147, 140, 134, 128, 122, 116, 111, 105, 100, 95, 90, 86, 81, 77, 73, 70, 66, 63, 60, 57, 54, 51, 48, 46, 44, 41, 39], + "IOB": [208, 207, 204, 202, 199, 195, 191, 186, 181, 176, 170, 164, 158, 152, 146, 140, 135, 129, 124, 119, 114, 110, 106, 101, 98, 94, 90, 87, 84, 81, 78, 75, 73, 70, 68, 66, 63, 61, 60, 58, 56, 55, 53, 52, 51, 49, 48, 47] + }, + "rate": 0, + "insulinReq": 0, + "insulinForManualBolus": -0.73, + "ISF": 3, + "expectedDelta": -5, + "deliverAt": "2025-01-12T13:26:45.570Z", + "duration": 120, + "reservoir": 170.2, + "insulin": { + "scheduled_basal": 0, + "bolus": 25.3, + "temp_basal": 5.9, + "TDD": 31.2 + }, + "COB": 0, + "minGuardBG": 22, + "timestamp": "2025-01-12T13:26:51.167Z", + "sensitivityRatio": 1.485721936996895 + } + }, + "pump": { + "status": { + "bolusing": false, + "timestamp": "2025-01-12T13:26:49.736Z", + "suspended": false, + "status": "normal" + }, + "clock": "2025-01-12T13:26:53.477Z", + "reservoir": 170.2, + "battery": { + "string": "normal", + "display": true, + "percent": 100 + } + }, + "uploader": { + "battery": 100 + }, + "utcOffset": 60 + } +] \ No newline at end of file diff --git a/tests/openaps.missingPill.test.js b/tests/openaps.missingPill.test.js new file mode 100644 index 00000000000..6d7286843fe --- /dev/null +++ b/tests/openaps.missingPill.test.js @@ -0,0 +1,63 @@ +'use strict'; + +const _ = require('lodash'); +const should = require('should'); +const helper = require('./inithelper')(); +const openaps = require('../lib/plugins/openaps')(helper.getctx()); +const sandbox = require('../lib/sandbox')(helper.getctx()); + +// Load test data +const missingRateOnLastEnacted = require('./data/missingRateOnLastEnacted.json'); +const workingStatus = require('./data/statusWithWorkingForecast.json'); + +describe('OpenAPS Visualization Tests', function () { + let ctx, now; + + beforeEach(function () { + let top_ctx = helper.getctx(); + now = top_ctx.moment(missingRateOnLastEnacted[0].created_at); + _.forEach(missingRateOnLastEnacted, function updateMills (status) { + status.mills = top_ctx.moment(status.created_at).valueOf(); + }); + _.forEach(workingStatus, function updateMills (status) { + status.mills = top_ctx.moment(status.created_at).valueOf(); + }); + ctx = { + settings: { + units: 'mg/dl', + }, + pluginBase: { + updatePillText: function mockedUpdatePillText(plugin, options) { + options.label.should.equal('OpenAPS ⌁'); + } + , addForecastPoints: function mockAddForecastPoints (points) { + points.length.should.greaterThan(100); + } + }, + language: top_ctx.language, + levels: top_ctx.levels, + }; + }); + + it('should correctly generate pill and prediction lines for working status', function (done) { + const sbx = sandbox.clientInit(ctx, now.valueOf(), { devicestatus: workingStatus }); + openaps.setProperties(sbx); + openaps.updateVisualisation(sbx); + + const result = sbx.properties.openaps; + should.exist(result.lastPredBGs); + result.lastPredBGs.UAM.should.be.an.Array(); + done(); + }); + + it('should correctly generate pill and prediction lines for status without rate on last enacted', function (done) { + const sbx = sandbox.clientInit(ctx, now.valueOf(), { devicestatus: missingRateOnLastEnacted }); + openaps.setProperties(sbx); + openaps.updateVisualisation(sbx); + + const result = sbx.properties.openaps; + should.exist(result.lastPredBGs); + result.lastPredBGs.UAM.should.be.an.Array(); + done(); + }); +});