var dateBegin = "2015-03-05";
var dateEnd = "2015-04-14";
var DataTypes = {"interday":0, "intraday":1};
var dataType = DataTypes.intraday;
var sedentaryThresholdInMinutes = 15;
var CONSUMER_KEY_PROPERTY_NAME = "fitbitConsumerKey";
var CONSUMER_SECRET_PROPERTY_NAME = "fitbitConsumerSecret";
function refreshTimeSeries() {
renderFitbitConfigurationDialog();
var doc = SpreadsheetApp.getActiveSpreadsheet();
doc.getRange("a1").setValue(user.fullName);
doc.getRange("a1").setComment("DOB:" + user.dateOfBirth)
doc.getRange("b1").setValue(user.country + "/" + user.state + "/" + user.city);
"oAuthServiceName": identifier,
"oAuthUseToken": "always",
if (dataType == DataTypes.interday) {
var activities = ["activities/log/steps", "activities/log/distance", "activities/log/activeScore", "activities/log/calories",
"activities/log/minutesSedentary", "activities/log/minutesLightlyActive", "activities/log/minutesFairlyActive", "activities/log/minutesVeryActive",
"sleep/timeInBed", "sleep/minutesAsleep", "sleep/awakeningsCount",
var interdays = ['activities-log-steps', 'activities-log-distance', 'activities-log-activeScore',
'activities-log-calories', 'activities-log-minutesSedentary', 'activities-log-minutesLightlyActive',
'activities-log-minutesFairlyActive', 'activities-log-minutesVeryActive',
'sleep-timeInBed', 'sleep-minutesAsleep', 'sleep-awakeningsCount',
else if (dataType == DataTypes.intraday) {
var activities = ["activities/log/steps", "activities/log/calories"];
var intradays = ["activities-log-steps-intraday", "activities-log-calories-intraday"];
for (var activity in activities) {
var dateString = dateBegin;
date = parseDate(dateString);
var currentActivity = activities[activity];
if (dataType == DataTypes.interday) {
var result = UrlFetchApp.fetch("https://api.fitbit.com/1/user/-/" + currentActivity + "/date/" + dateString
+ "/" + period + ".json", options);
else if (dataType == DataTypes.intraday) {
var result = UrlFetchApp.fetch("https://api.fitbit.com/1/user/-/" + currentActivity + "/date/" + dateString+ "/" + dateString + ".json", options);
var o = Utilities.jsonParse(result.getContentText());
var cell = doc.getRange('a3');
var titleCell = doc.getRange("a2");
titleCell.setValue("Date");
var title = currentActivity.split("/");
title = title[title.length - 1];
titleCell.offset(0, 1 + activity * 1.0).setValue(title);
if (dataType == DataTypes.intraday) {
var row = o[intradays[activity]]["dataset"];
else if (dataType == DataTypes.interday) {
var row = o[interdays[activity]];
if (dataType == DataTypes.interday) {
cell.offset(index, 0).setValue(val["dateTime"]);
else if (dataType == DataTypes.intraday) {
cell.offset(index, 0).setValue(dateString + ' ' + val["time"]);
cell.offset(index, 1 + activity * 1.0).setValue(val["value"]);
if (dateBegin == dateEnd) {
date.setDate(date.getDate()+1);
dateString = Utilities.formatDate(date, "GMT", "yyyy-MM-dd");
if (dateString > dateEnd) {
function isConfigured() {
return getConsumerKey() != "" && getConsumerSecret() != "";
function getConsumerKey() {
var key = getScriptProperty(CONSUMER_KEY_PROPERTY_NAME);
function setConsumerKey(key) {
setScriptProperty(CONSUMER_KEY_PROPERTY_NAME, key);
function getConsumerSecret() {
var secret = getScriptProperty(CONSUMER_SECRET_PROPERTY_NAME);
function setConsumerSecret(secret) {
setScriptProperty(CONSUMER_SECRET_PROPERTY_NAME, secret);
function saveConfiguration(e) {
setConsumerKey(e.parameter.consumerKey);
setConsumerSecret(e.parameter.consumerSecret);
var app = UiApp.getActiveApplication();
function renderFitbitConfigurationDialog() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication().setTitle(
app.setStyleAttribute("padding", "10px");
var helpLabel = app.createLabel(
"From here you will configure access to fitbit -- Just supply your own"
+ "consumer key and secret \n\n"
+ "Important: To authroize this app you need to load the script in the script editor"
+ " (tools->Script Manager) and then run the 'authorize' script.");
helpLabel.setStyleAttribute("text-align", "justify");
helpLabel.setWidth("95%");
var consumerKeyLabel = app.createLabel(
"Fitbit OAuth Consumer Key:");
var consumerKey = app.createTextBox();
consumerKey.setName("consumerKey");
consumerKey.setWidth("100%");
consumerKey.setText(getConsumerKey());
var consumerSecretLabel = app.createLabel(
"Fitbit OAuth Consumer Secret:");
var consumerSecret = app.createTextBox();
consumerSecret.setName("consumerSecret");
consumerSecret.setWidth("100%");
consumerSecret.setText(getConsumerSecret());
var saveHandler = app.createServerClickHandler("saveConfiguration");
var saveButton = app.createButton("Save Configuration", saveHandler);
var listPanel = app.createGrid(4, 2);
listPanel.setStyleAttribute("margin-top", "10px")
listPanel.setWidth("90%");
listPanel.setWidget(1, 0, consumerKeyLabel);
listPanel.setWidget(1, 1, consumerKey);
listPanel.setWidget(2, 0, consumerSecretLabel);
listPanel.setWidget(2, 1, consumerSecret);
saveHandler.addCallbackElement(listPanel);
var dialogPanel = app.createFlowPanel();
dialogPanel.add(helpLabel);
dialogPanel.add(listPanel);
dialogPanel.add(saveButton);
var oAuthConfig = UrlFetchApp.addOAuthService(identifier);
oAuthConfig.setAccessTokenUrl("https://api.fitbit.com/oauth/access_token");
oAuthConfig.setRequestTokenUrl("https://api.fitbit.com/oauth/request_token");
oAuthConfig.setAuthorizationUrl("https://api.fitbit.com/oauth/authorize");
oAuthConfig.setConsumerKey(getConsumerKey());
oAuthConfig.setConsumerSecret(getConsumerSecret());
"oAuthServiceName": identifier,
"oAuthUseToken": "always",
var result = UrlFetchApp.fetch("https://api.fitbit.com/1/user/-/profile.json", options);
var o = Utilities.jsonParse(result.getContentText());
var ss = SpreadsheetApp.getActiveSpreadsheet();
functionName: "renderFitbitConfigurationDialog"
functionName: "authorize"
functionName: "refreshTimeSeries"
name: "Find Sedendtary Time",
functionName: "findSedentaryBouts"
ss.addMenu(identifier, menuEntries);
function parseDate(input) {
var parts = input.match(/(\d+)/g);
return new Date(parts[0], parts[1]-1, parts[2]);
function parseDate2(input) {
var parts = input.match(/(\d+)/g);
return new Date(parts[0], parts[1]-1, parts[2], parts[3], parts[4]);
function getAwakeTime(dateString) {
renderFitbitConfigurationDialog();
"oAuthServiceName": identifier,
"oAuthUseToken": "always",
var date = new Date(parseDate(dateString));
for (var i=0; i<2; i++) {
result = UrlFetchApp.fetch("https://api.fitbit.com/1/user/-/sleep/date/" + dateString + ".json", options);
var o = Utilities.jsonParse(result.getContentText());
for (var j in sleepLogs) {
var sleepLog = sleepLogs[j];
if (sleepLog["isMainSleep"] == true) {
sleepTimePreviousDay = parseDate2(sleepLog["startTime"]);
Logger.log(sleepTimePreviousDay);
wakeTime = new Date(sleepTimePreviousDay);
wakeTime.setMinutes (sleepTimePreviousDay.getMinutes() + sleepLog["timeInBed"]);
sleepTime = parseDate2(sleepLog["startTime"]);
date.setDate(date.getDate()+1);
dateString = Utilities.formatDate(date, "GMT", "yyyy-MM-dd");
function getMinutesFromMidnight(date) {
return date.getHours()*60+date.getMinutes();
function findSedentaryBouts() {
var sedentaryTimeRanges = new Array();
var doc = SpreadsheetApp.getActiveSpreadsheet();
var cell = doc.getRange('b4');
var outputCell = doc.getRange('e3');
for (var day=0; day < daysToProcess; day++) {
currentDate = cell.offset(0,-1).getValue();
awakeTimes = getAwakeTime(Utilities.formatDate(currentDate, "GMT", "yyyy-MM-dd"));
if (awakeTimes.wakeTime != null) {
startMinutes = getMinutesFromMidnight(awakeTimes.wakeTime);
if (awakeTimes.sleepTime != null) {
endMinutes = getMinutesFromMidnight(awakeTimes.sleepTime);
Logger.log(startMinutes);
for (var i = startMinutes+day*24*60; i <= endMinutes+day*24*60; i++) {
if (cell.offset(i, 0).getValue() == 0) {
var sedentary_start_time = cell.offset(i, -1).getValue();
if (zero_count > sedentaryThresholdInMinutes) {
sedentaryTimeRanges[k] = new Array(2);
sedentaryTimeRanges[k][0] = sedentary_start_time;
outputCell.offset(k,0).setValue(sedentaryTimeRanges[k][0]);
sedentaryTimeRanges[k][1] = zero_count;
outputCell.offset(k,1).setValue(sedentaryTimeRanges[k][1]);
function setScriptProperty(key,value) {
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperty(key, value)
function getScriptProperty(key) {
var scriptProperties = PropertiesService.getScriptProperties();
return scriptProperties.getProperty(key)