From 1f83a1e16c1145d2b0b3d7efe36b0eae1dbfbae1 Mon Sep 17 00:00:00 2001 From: Mark Setrem Date: Fri, 16 Oct 2015 21:11:51 +0100 Subject: [PATCH 1/2] added weight added options to sync from Fitbit Aria scales (weight) and updated links to titbit documentation throughout --- fitbit/fitbit.html | 23 ++++++++--- fitbit/fitbit.js | 71 +++++++++++++++++++++++++++++--- fitbit/locales/en-US/fitbit.json | 4 +- 3 files changed, 86 insertions(+), 12 deletions(-) mode change 100644 => 100755 fitbit/fitbit.html mode change 100644 => 100755 fitbit/fitbit.js mode change 100644 => 100755 fitbit/locales/en-US/fitbit.json diff --git a/fitbit/fitbit.html b/fitbit/fitbit.html old mode 100644 new mode 100755 index 4e29e5c5..77fbe835 --- a/fitbit/fitbit.html +++ b/fitbit/fitbit.html @@ -154,6 +154,7 @@ @@ -169,15 +170,19 @@ as follows:

goals
-
Messages are sent when a daily goal is reached. The message payload contains an achievement message and the message data property contains the current Messages are sent when a daily goal is reached. The message payload contains an achievement message and the message data property contains the current activities data.
sleep
Messages are sent when a new daily sleep record becomes available. The message payload contains sleep log data.
+
Weight
+
Messages are sent when a new weight record becomes available. The message payload contains the latest entry in the days weight log.
badges
Messages are sent when a new badge is earned. The message payload contains the badge message and the message data property contains a single badge entry from the list returned by the badges API call.
@@ -213,6 +218,7 @@ @@ -229,16 +235,21 @@
activities
the message payload contains daily activities data.
sleep
the message payload contains sleep log data for the main sleep and the message data property contains the complete sleep data result.
+
weight
+
the message payload contains the latest entry in the days weight log and the message + data property contains the complete days weight entry.
badges
the message payload contains data about badges awarded.

The msg.date property may be set to an ISO 8601 format diff --git a/fitbit/fitbit.js b/fitbit/fitbit.js old mode 100644 new mode 100755 index c3de9191..fe654c70 --- a/fitbit/fitbit.js +++ b/fitbit/fitbit.js @@ -180,7 +180,55 @@ module.exports = function(RED) { }); node.setInterval(); }); - } else if (node.dataType === 'goals') { + } else if (node.dataType === 'weight') { + oa.get('https://api.fitbit.com/1/user/-/body/log/weight/date/'+day+'.json', + credentials.access_token, + credentials.access_token_secret, + function(err, body, response) { + if (err) { + node.error(formatError(err)); + node.status({fill:"red",shape:"ring",text:"fitbit.status.failed"}); + return; + } + var data = JSON.parse(body); + if( data.weight.length > 0){ + node.state = { + logId: data.weight[data.weight.length-1].logId, + }; + } + else { + node.state = { + logId: null, + }; + } + node.status({}); + node.on('input', function(msg) { + node.status({fill:"blue",shape:"dot",text:"fitbit.status.querying"}); + var day = today(); + oa.get('https://api.fitbit.com/1/user/-/body/log/weight/date/'+day+'.json', + credentials.access_token, + credentials.access_token_secret, + function(err, body, response) { + if (err) { + node.error(formatError(err),msg); + node.status({fill:"red",shape:"ring",text:"fitbit.status.failed"}); + return; + } + var data = JSON.parse(body); + if( data.weight.length > 0){ + if(data.weight[data.weight.length-1].logId != node.state.logId){ + node.send({ payload: data.weight[data.weight.length-1] }); + node.state = { + logId: data.weight[data.weight.length-1].logId, + }; + } + } + node.status({}); + }); + }); + node.setInterval(); + }); + }else if (node.dataType === 'goals') { oa.get('https://api.fitbit.com/1/user/-/activities/date/'+day+'.json', credentials.access_token, credentials.access_token_secret, @@ -255,7 +303,7 @@ module.exports = function(RED) { }; FitbitInNode.prototype.setInterval = function(repeat) { - repeat = repeat || 900000; // 15 minutes + repeat = repeat || 300000; // 15 minutes var node = this; var interval = setInterval(function() { node.emit("input", {}); @@ -271,7 +319,7 @@ module.exports = function(RED) { RED.nodes.createNode(this,n); this.fitbitConfig = RED.nodes.getNode(n.fitbit); this.dataType = n.dataType || 'activities'; - var supportedTypes = ["activities","sleep","badges"]; + var supportedTypes = ["activities","sleep","weight","badges"]; if (supportedTypes.indexOf(this.dataType) == -1) { this.error(RED._("fitbit.error.unsupported-data-type")); return; @@ -281,8 +329,7 @@ module.exports = function(RED) { return; } var credentials = this.fitbitConfig.credentials; - if (credentials && - credentials.access_token && credentials.access_token_secret) { + if (credentials && credentials.access_token && credentials.access_token_secret) { var oa = getOAuth(credentials.client_key,credentials.client_secret); var node = this; this.on('input', function(msg) { @@ -295,6 +342,9 @@ module.exports = function(RED) { node.dataType + '/date/' + day + '.json'; } else if (node.dataType === 'badges') { url = 'https://api.fitbit.com/1/user/-/badges.json'; + } else if (node.dataType === 'weight') { + var day = msg.date || today(); + url = 'https://api.fitbit.com/1/user/-/body/log/weight/date/' + day + '.json'; } oa.get(url, credentials.access_token, @@ -311,11 +361,22 @@ module.exports = function(RED) { var sleep = mainSleep(data.sleep); if (!sleep) { node.warn(RED._("fitbit.warn.no-sleep-record")); + node.status({}); return; } else { msg.payload = sleep; delete msg.error; } + } else if (node.dataType === 'weight') { + if( data.weight.length > 0) { + msg.payload = data.weight.reverse(); + msg.data = data.weight[data.weight.length-1]; + delete msg.error; + } else { + node.warn(RED._("fitbit.warn.no-weight-record")+" "+day); + node.status({}); + return; + } } else { msg.payload = data; } diff --git a/fitbit/locales/en-US/fitbit.json b/fitbit/locales/en-US/fitbit.json old mode 100644 new mode 100755 index acbaaa27..aa3eb581 --- a/fitbit/locales/en-US/fitbit.json +++ b/fitbit/locales/en-US/fitbit.json @@ -5,6 +5,7 @@ "type": "Type", "goals": "goals", "sleep": "sleep", + "weight": "weight", "badges": "badges", "activities": "activities", "name": "Name", @@ -22,7 +23,8 @@ }, "warn": { "missing-credentials": "Missing fitbit credentials", - "no-sleep-record": "no main sleep record found" + "no-sleep-record": "No main sleep record found", + "no-weight-record": "No weight record returned for" }, "error": { "unsupported-data-type": "Unsupported data type", From cbc79c55f3d45ee42d8391ddacb12e112f0fa74b Mon Sep 17 00:00:00 2001 From: Mark Setrem Date: Fri, 16 Oct 2015 21:17:27 +0100 Subject: [PATCH 2/2] corrected repeat time corrected repeat time back to 15 mins --- fitbit/fitbit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fitbit/fitbit.js b/fitbit/fitbit.js index fe654c70..4e7caa8f 100755 --- a/fitbit/fitbit.js +++ b/fitbit/fitbit.js @@ -303,7 +303,7 @@ module.exports = function(RED) { }; FitbitInNode.prototype.setInterval = function(repeat) { - repeat = repeat || 300000; // 15 minutes + repeat = repeat || 900000; // 15 minutes var node = this; var interval = setInterval(function() { node.emit("input", {});