Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/plugins/add-virtual-assistant-support-to-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ There are 2 types of handlers that you can supply:

A plugin can expose multiple intent handlers (e.g. useful when it can supply multiple kinds of metrics). Each intent handler should be structured as follows:
+ `intent` - This is the intent this handler is built for. Right now, the templates used by both Alexa and Google Home use only the `"MetricNow"` intent (used for getting the present value of the requested metric)
+ `metrics` - An array of metric name(s) the handler will supply. e.g. "What is my `metric`" - iob, bg, cob, etc. Make sure to add the metric name and its synonyms to the list of metrics used by the virtual assistant(s).
- **IMPORTANT NOTE:** There is no protection against overlapping metric names, so PLEASE make sure your metric name is unique!
- Note: Although this value *is* an array, you really should only supply one (unique) value, and then add aliases or synonyms to that value in the list of metrics for the virtual assistant. We keep this value as an array for backwards compatibility.
+ `metrics` - An array of metric name(s) the handler will supply. e.g. "What is my `metric`" - iob, bg, cob, etc. Although this value *is* an array, you really should only supply one (unique) value, and then add aliases or synonyms to that value in the list of metrics for the virtual assistant. We keep this value as an array for backwards compatibility.
- **IMPORTANT NOTE:** There is no protection against overlapping metric names, so PLEASE make sure your metric name is unique!
+ `intenthandler` - This is a callback function that receives 3 arguments:
- `callback` Call this at the end of your function. It requires 2 arguments:
- `title` - Title of the handler. This is the value that will be displayed on the Alexa card (for devices with a screen). The Google Home response doesn't currently display a card, so it doesn't use this value.
Expand Down
20 changes: 6 additions & 14 deletions lib/api/alexa/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

var _ = require('lodash');
var moment = require('moment');

function configure (app, wares, ctx, env) {
Expand All @@ -18,7 +19,7 @@ function configure (app, wares, ctx, env) {

api.post('/alexa', ctx.authorization.isPermitted('api:*:read'), function (req, res, next) {
console.log('Incoming request from Alexa');
var locale = req.body.request.locale;
var locale = _.get(req, 'body.request.locale');
if(locale){
if(locale.length > 2) {
locale = locale.substr(0, 2);
Expand Down Expand Up @@ -78,19 +79,10 @@ function configure (app, wares, ctx, env) {
function handleIntent(intentName, slots, next) {
var metric;
if (slots) {
if (slots.metric
&& slots.metric.resolutions
&& slots.metric.resolutions.resolutionsPerAuthority
&& slots.metric.resolutions.resolutionsPerAuthority.length
&& slots.metric.resolutions.resolutionsPerAuthority[0].status
&& slots.metric.resolutions.resolutionsPerAuthority[0].status.code
&& slots.metric.resolutions.resolutionsPerAuthority[0].status.code == "ER_SUCCESS_MATCH"
&& slots.metric.resolutions.resolutionsPerAuthority[0].values
&& slots.metric.resolutions.resolutionsPerAuthority[0].values.length
&& slots.metric.resolutions.resolutionsPerAuthority[0].values[0].value
&& slots.metric.resolutions.resolutionsPerAuthority[0].values[0].value.name
){
metric = slots.metric.resolutions.resolutionsPerAuthority[0].values[0].value.name;
var slotStatus = _.get(slots, 'metric.resolutions.resolutionsPerAuthority[0].status.code');
var slotName = _.get(slots, 'metric.resolutions.resolutionsPerAuthority[0].values[0].value.name');
if (slotStatus == "ER_SUCCESS_MATCH" && slotName) {
metric = slotName;
} else {
next(translate('virtAsstUnknownIntentTitle'), translate('virtAsstUnknownIntentText'));
return;
Expand Down
3 changes: 2 additions & 1 deletion lib/api/googlehome/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

var _ = require('lodash');
var moment = require('moment');

function configure (app, wares, ctx, env) {
Expand All @@ -18,7 +19,7 @@ function configure (app, wares, ctx, env) {

api.post('/googlehome', ctx.authorization.isPermitted('api:*:read'), function (req, res, next) {
console.log('Incoming request from Google Home');
var locale = req.body.queryResult.languageCode;
var locale = _.get(req, 'body.queryResult.languageCode');
if(locale){
if(locale.length > 2) {
locale = locale.substr(0, 2);
Expand Down
5 changes: 3 additions & 2 deletions lib/plugins/ar2.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ function init (ctx) {
};

function virtAsstAr2Handler (next, slots, sbx) {
if (sbx.properties.ar2.forecast.predicted) {
var forecast = sbx.properties.ar2.forecast.predicted;
var predicted = _.get(sbx, 'properties.ar2.forecast.predicted');
if (predicted) {
var forecast = predicted;
var max = forecast[0].mgdl;
var min = forecast[0].mgdl;
var maxForecastMills = forecast[0].mills;
Expand Down
18 changes: 7 additions & 11 deletions lib/plugins/basalprofile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
var times = require('../times');
var moment = require('moment');
var consts = require('../constants');
var _ = require('lodash');

function init (ctx) {

Expand Down Expand Up @@ -114,13 +115,13 @@ function init (ctx) {
function basalMessage(slots, sbx) {
var basalValue = sbx.data.profile.getTempBasal(sbx.time);
var response = translate('virtAsstUnknown');
var preamble = '';
var pwd = _.get(slots, 'pwd.value');
var preamble = pwd ? translate('virtAsstPreamble3person', {
params: [
pwd
]
}) : translate('virtAsstPreamble');
if (basalValue.treatment) {
preamble = (slots && slots.pwd && slots.pwd.value) ? translate('virtAsstPreamble3person', {
params: [
slots.pwd.value
]
}) : translate('virtAsstPreamble');
var minutesLeft = moment(basalValue.treatment.endmills).from(moment(sbx.time));
response = translate('virtAsstBasalTemp', {
params: [
Expand All @@ -130,11 +131,6 @@ function init (ctx) {
]
});
} else {
preamble = (slots && slots.pwd && slots.pwd.value) ? translate('virtAsstPreamble3person', {
params: [
slots.pwd.value
]
}) : translate('virtAsstPreamble');
response = translate('virtAsstBasal', {
params: [
preamble,
Expand Down
8 changes: 5 additions & 3 deletions lib/plugins/cob.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,13 @@ function init (ctx) {

function virtAsstCOBHandler (next, slots, sbx) {
var response = '';
var value = (sbx.properties.cob && sbx.properties.cob.cob) ? sbx.properties.cob.cob : 0;
if (slots && slots.pwd && slots.pwd.value) {
var cob = _.get(sbx, 'properties.cob.cob');
var pwd = _.get(slots, 'pwd.value');
var value = cob ? cob : 0;
if (pwd) {
response = translate('virtAsstCob3person', {
params: [
slots.pwd.value.replace('\'s', '')
pwd.replace('\'s', '')
, value
]
});
Expand Down
10 changes: 7 additions & 3 deletions lib/plugins/dbsize.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

var levels = require('../levels');
var _ = require('lodash');

function init (ctx) {
var translate = ctx.language.translate;
Expand Down Expand Up @@ -117,11 +118,14 @@ function init (ctx) {
};

function virtAsstDatabaseSizeHandler (next, slots, sbx) {
if (sbx.properties.dbsize.display) {
var display = _.get(sbx, 'properties.dbsize.display');
var dataSize = _.get(sbx, 'properties.dbsize.details.dataSize');
var dataPercentage = _.get(sbx, 'properties.dbsize.dataPercentage');
if (display) {
var response = translate('virtAsstDatabaseSize', {
params: [
sbx.properties.dbsize.details.dataSize
, sbx.properties.dbsize.dataPercentage
dataSize
, dataPercentage
]
});
next(translate('virtAsstTitleDatabaseSize'), response);
Expand Down
5 changes: 3 additions & 2 deletions lib/plugins/iob.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,11 @@ function init(ctx) {
}

function getIob(sbx) {
if (sbx.properties.iob && sbx.properties.iob.iob !== 0) {
var iob = _.get(sbx, 'properties.iob.iob');
if (iob !== 0) {
return translate('virtAsstIobUnits', {
params: [
utils.toFixed(sbx.properties.iob.iob)
utils.toFixed(iob)
]
});
}
Expand Down
12 changes: 7 additions & 5 deletions lib/plugins/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -529,13 +529,14 @@ function init (ctx) {
};

function virtAsstForecastHandler (next, slots, sbx) {
if (sbx.properties.loop.lastLoop.predicted) {
var forecast = sbx.properties.loop.lastLoop.predicted.values;
var predicted = _.get(sbx, 'properties.loop.lastLoop.predicted');
if (predicted) {
var forecast = predicted.values;
var max = forecast[0];
var min = forecast[0];
var maxForecastIndex = Math.min(6, forecast.length);

var startPrediction = moment(sbx.properties.loop.lastLoop.predicted.startDate);
var startPrediction = moment(predicted.startDate);
var endPrediction = startPrediction.clone().add(maxForecastIndex * 5, 'minutes');
if (endPrediction.valueOf() < sbx.time) {
next(translate('virtAsstTitleLoopForecast'), translate('virtAsstForecastUnavailable'));
Expand Down Expand Up @@ -573,8 +574,9 @@ function init (ctx) {
}

function virtAsstLastLoopHandler (next, slots, sbx) {
if (sbx.properties.loop.lastLoop) {
console.log(JSON.stringify(sbx.properties.loop.lastLoop));
var lastLoop = _.get(sbx, 'properties.loop.lastLoop')
if (lastLoop) {
console.log(JSON.stringify(lastLoop));
var response = translate('virtAsstLastLoop', {
params: [
moment(sbx.properties.loop.lastOkMoment).from(moment(sbx.time))
Expand Down
11 changes: 6 additions & 5 deletions lib/plugins/openaps.js
Original file line number Diff line number Diff line change
Expand Up @@ -560,10 +560,11 @@ function init (ctx) {
};

function virtAsstForecastHandler (next, slots, sbx) {
if (sbx.properties.openaps && sbx.properties.openaps.lastEventualBG) {
var lastEventualBG = _.get(sbx, 'properties.openaps.lastEventualBG');
if (lastEventualBG) {
var response = translate('virtAsstOpenAPSForecast', {
params: [
sbx.properties.openaps.lastEventualBG
lastEventualBG
]
});
next(translate('virtAsstTitleOpenAPSForecast'), response);
Expand All @@ -573,11 +574,11 @@ function init (ctx) {
}

function virtAsstLastLoopHandler (next, slots, sbx) {
if (sbx.properties.openaps.lastLoopMoment) {
console.log(JSON.stringify(sbx.properties.openaps.lastLoopMoment));
var lastLoopMoment = _.get(sbx, 'properties.openaps.lastLoopMoment');
if (lastLoopMoment) {
var response = translate('virtAsstLastLoop', {
params: [
moment(sbx.properties.openaps.lastLoopMoment).from(moment(sbx.time))
moment(lastLoopMoment).from(moment(sbx.time))
]
});
next(translate('virtAsstTitleLastLoop'), response);
Expand Down
2 changes: 1 addition & 1 deletion lib/plugins/pump.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function init (ctx) {
};

function virtAsstReservoirHandler (next, slots, sbx) {
var reservoir = sbx.properties.pump.pump.reservoir;
var reservoir = _.get(sbx, 'properties.pump.pump.reservoir');
if (reservoir || reservoir === 0) {
var response = translate('virtAsstReservoir', {
params: [
Expand Down
5 changes: 3 additions & 2 deletions lib/plugins/rawbg.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ function init (ctx) {
};

function virtAsstRawBGHandler (next, slots, sbx) {
if (sbx.properties.rawbg.mgdl) {
var rawBg = _.get(sbx, 'properties.rawbg.mgdl');
if (rawBg) {
var response = translate('virtAsstRawBG', {
params: [
sbx.properties.rawbg.mgdl
rawBg
]
});
next(translate('virtAsstTitleRawBG'), response);
Expand Down
5 changes: 3 additions & 2 deletions lib/plugins/upbat.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,11 @@ function init(ctx) {
};

function virtAsstUploaderBatteryHandler (next, slots, sbx) {
if (sbx.properties.upbat.display) {
var upBat = _.get(sbx, 'properties.upbat.display');
if (upBat) {
var response = translate('virtAsstUploaderBattery', {
params: [
sbx.properties.upbat.display
upBat
]
});
next(translate('virtAsstTitleUploaderBattery'), response);
Expand Down
35 changes: 20 additions & 15 deletions lib/plugins/xdripjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,11 @@ function init(ctx) {

function virtAsstGenericCGMHandler(translateItem, field, next, sbx) {
var response;
if (sbx.properties.sensorState && sbx.properties.sensorState[field]) {
var state = _.get(sbx, 'properties.sensorState.'+field);
if (state) {
response = translate('virtAsstCGM'+translateItem, {
params:[
sbx.properties.sensorState[field]
state
, moment(sbx.properties.sensorState.lastStateTime).from(moment(sbx.time))
]
});
Expand Down Expand Up @@ -355,10 +356,11 @@ function init(ctx) {
, metrics: ['cgm session age']
, intentHandler: function(next, slots, sbx){
var response;
var lastSessionStart = _.get(sbx, 'properties.sensorState.lastSessionStart');
// session start is only valid if in a session
if (sbx.properties.sensorState && sbx.properties.sensorState.lastSessionStart) {
if (sbx.properties.sensorState.lastState != 0x1) {
var duration = moment.duration(moment().diff(moment(sbx.properties.sensorState.lastSessionStart)));
if (lastSessionStart) {
if (_.get(sbx, 'properties.sensorState.lastState') != 0x1) {
var duration = moment.duration(moment().diff(moment(lastSessionStart)));
response = translate('virtAsstCGMSessAge', {
params: [
duration.days(),
Expand All @@ -384,10 +386,11 @@ function init(ctx) {
intent: 'MetricNow'
, metrics: ['cgm tx age']
, intentHandler: function(next, slots, sbx){
var lastTxActivation = _.get(sbx, 'properties.sensorState.lastTxActivation');
next(
translate('virtAsstTitleCGMTxAge'),
(sbx.properties.sensorState && sbx.properties.sensorState.lastTxActivation)
? translate('virtAsstCGMTxAge', {params:[moment().diff(moment(sbx.properties.sensorState.lastTxActivation), 'days')]})
lastTxActivation
? translate('virtAsstCGMTxAge', {params:[moment().diff(moment(lastTxActivation), 'days')]})
: translate('virtAsstUnknown')
);
}
Expand All @@ -402,22 +405,24 @@ function init(ctx) {
, metrics: ['cgm battery']
, intentHandler: function(next, slots, sbx){
var response;
var sensor = sbx.properties.sensorState;
if (sensor && (sensor.lastVoltageA || sensor.lastVoltageB)) {
if (sensor.lastVoltageA && sensor.lastVoltageB) {
var lastVoltageA = _.get(sbx, 'properties.sensorState.lastVoltageA');
var lastVoltageB = _.get(sbx, 'properties.sensorState.lastVoltageB');
var lastBatteryTimestamp = _.get(sbx, 'properties.sensorState.lastBatteryTimestamp');
if (lastVoltageA || lastVoltageB) {
if (lastVoltageA && lastVoltageB) {
response = translate('virtAsstCGMBattTwo', {
params:[
(sensor.lastVoltageA / 100)
, (sensor.lastVoltageB / 100)
, moment(sensor.lastBatteryTimestamp).from(moment(sbx.time))
(lastVoltageA / 100)
, (lastVoltageB / 100)
, moment(lastBatteryTimestamp).from(moment(sbx.time))
]
});
} else {
var finalValue = sensor.lastVoltageA ? sensor.lastVoltageA : sensor.lastVoltageB;
var finalValue = lastVoltageA ? lastVoltageA : lastVoltageB;
response = translate('virtAsstCGMBattOne', {
params:[
(finalValue / 100)
, moment(sensor.lastBatteryTimestamp).from(moment(sbx.time))
, moment(lastBatteryTimestamp).from(moment(sbx.time))
]
});
}
Expand Down