-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathlambda.js
More file actions
153 lines (126 loc) · 4.41 KB
/
Copy pathlambda.js
File metadata and controls
153 lines (126 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* AWS Lambda function that is periodically invoked to determine if a Fitbit
* user has been sedentary over over the last hour. The function retrieves
* the Fitbit intra-day step count for the user up to the current time
* period and notifies the user through the AWS Simple Notification Service (SNS)
* to get moving.
*
* Event Flow:
* 1. AWS CloudWatch Event is triggered hourly using a defined Scheduled Rule
* 2. The scheduled rule invokes the AWS Lambda function
* 3. The lambda function fetches the step count for the user for the past hour
* 4. If the hourly step goal is not met, a notification message is sent to
* AWS SNS
* 5. AWS SNS sends an SMS text message to the user to move around
*
* @param event AWS event object containing event data
* @param context execution context of the function
* @param callback Optional callback to return information to the caller.
*/
exports.handler = function(event, context, callback) {
"use strict";
// Retrieve the access token from the invoker
const accessToken = event.accessToken;
// Retrieve the hourly step threshold (# of step needed to be met to avoid
// considered to be sedentary)
const minHourlySteps = event.minHourlySteps;
// The Amazon resource name for the SNS topic
const snsTopicArn = event.snsTopicArn;
// The AWS region in which SNS topic resides
const snsTopicRegion = event.snsTopicRegion;
// Base Fitbit URL
const fitbitBaseUrl = "https://api.fitbit.com/1/user/-/";
// Load the axios http lib.
const axios = require('axios');
// Promise lib.
const Promise = require('promise');
/*
1. Determine the Profile's UTC Offset
2. Get Intraday Steps
3. Compute current steps and send notification if applicable
*/
getFitbitProfileUTCOffset().
then(getIntradaySteps).
then(function(dataset) {
//Needs to be above our threshold
let stepCount = 0;
console.log(`dataset.length=${dataset.length}`);
for (let index = 0; index < dataset.length; ++index) {
stepCount += dataset[index].value;
}
if (stepCount < minHourlySteps) {
let message = `You've only move ${stepCount} this hour. Get movin'!` ;
console.log(message);
// AWS SDK
const AWS = require('aws-sdk');
AWS.config.update({
'region': snsTopicRegion
});
//create and configure a new SNS client
let sns = new AWS.SNS();
// Init publish request parameters
let publishParams = {
TopicArn : snsTopicArn,
Message: message
};
/// Send SNS message
sns.publish(publishParams, function(err, data) {
console.log(`MessageId - ${data.MessageId}`);
});
}
callback(null, 'MoveNow Lambda function completed.');
}).catch(function (error) {
console.log('error', error);
callback(error);
});
/**
* Determines the user's time offset from UTC in milliseconds. This allows us to normalized
* the local time with the device's timezone. (at least the last recorded timezone)
* @return the UTC offset in milliseconds
*/
function getFitbitProfileUTCOffset() {
return axios({
url: fitbitBaseUrl + "profile.json",
method: 'GET',
headers: {
'Authorization': 'Bearer ' + accessToken
}
}).then(response => {
let offsetFromUTCMillis = response.data.user.offsetFromUTCMillis
console.log("User's UTC offest in milliseconds is: " + offsetFromUTCMillis);
return offsetFromUTCMillis;
}).catch(error => {
throw error;
});
}
/**
* Get the intraday steps for the current user using the input UTC offet
*/
function getIntradaySteps(offsetFromUTCMillis) {
// Moment.js library
const moment = require('moment')
//Get the current date/time and offset based on the Fitbit user's profile
let now = moment();
now.add(offsetFromUTCMillis, 'ms');
//Format date range values
let hourString = now.get('hour');
let dateString = now.format("YYYY-MM-DD");
//URL to fetch data for the current hour
let url = fitbitBaseUrl + `activities/steps/date/${dateString}/1d/15min/time/${hourString}:00/${hourString}:59.json`;
//Fetch the data from Fitbit
console.log("Invoking Fitbit endpoint at: " + url);
return axios({
url: url,
method: 'GET',
headers: {
'Authorization': 'Bearer ' + accessToken
}
}).then(response => {
console.log("Returned payload: \n" + JSON.stringify(response.data["activities-steps-intraday"]));
let dataset = response.data["activities-steps-intraday"].dataset;
return dataset;
}).catch(error => {
throw error;
});
}
}