Skip to content

Commit d7953ed

Browse files
committed
Merge pull request #28 from hindessm/fitbit
Fitbit node.
2 parents 490d780 + 6902e6f commit d7953ed

File tree

4 files changed

+1071
-0
lines changed

4 files changed

+1071
-0
lines changed

fitbit/fitbit.html

+268
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<!--
2+
Copyright 2014 IBM Corp.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
<script type="text/x-red" data-template-name="fitbit-credentials">
18+
<div id="node-config-fitbit-app-keys">
19+
<div class="form-row">
20+
<p style="margin-top: 10px;"><b>1.</b> Create your own app at <a href="https://dev.fitbit.com/apps/new" target="_blank" style="text-decoration:underline;">fitbit.com</a></p>
21+
</div>
22+
<div class="form-row">
23+
<p style="margin-top: 10px;"><b>2.</b> Copy the app details here:</p>
24+
</div>
25+
<div class="form-row">
26+
<label style="margin-left: 10px; margin-right: -10px;" for="node-config-input-client_key"><i class="fa fa-user"></i> Key</label>
27+
<input type="password" id="node-config-input-client_key">
28+
</div>
29+
<div class="form-row">
30+
<label style="margin-left: 10px; margin-right: -10px;" for="node-config-input-client_secret"><i class="fa fa-key"></i> Secret</label>
31+
<input type="password" id="node-config-input-client_secret">
32+
</div>
33+
<div class="form-row">
34+
<label>&nbsp;</label>
35+
<a class="btn" id="node-config-start-auth" href="#" target="_blank">Authenticate with Fitbit</a>
36+
</div>
37+
</div>
38+
<div id="node-config-fitbit-user">
39+
<div class="form-row">
40+
<label><i class="fa fa-user"></i> Fitbit ID</label><span id="node-config-fitbit-username" class="input-xlarge uneditable-input"></span>
41+
</div>
42+
<input type="hidden" id="node-config-input-username">
43+
</div>
44+
</script>
45+
46+
<script type="text/javascript">
47+
(function() {
48+
49+
RED.nodes.registerType('fitbit-credentials',{
50+
category: 'config',
51+
defaults: {
52+
username: {value:""}
53+
},
54+
credentials: {
55+
username: {type:"text"},
56+
client_key: { type: "password"},
57+
client_secret: { type: "password"},
58+
access_token: {type: "password"},
59+
access_token_secret: {type:"password"}
60+
},
61+
62+
label: function() {
63+
return this.username;
64+
},
65+
exportable: false,
66+
oneditprepare: function() {
67+
var id = this.id;
68+
69+
function updateFitbitAuthButton() {
70+
var v1 = $("#node-config-input-client_key").val();
71+
var v2 = $("#node-config-input-client_secret").val();
72+
73+
$("#node-config-start-auth").toggleClass("disabled",(v1.length === 0 || v2.length === 0));
74+
75+
}
76+
$("#node-config-input-client_key").on('change keydown paste input',updateFitbitAuthButton);
77+
$("#node-config-input-client_secret").on('change keydown paste input',updateFitbitAuthButton);
78+
79+
function updateFitbitScreenName(sn) {
80+
$("#node-config-fitbit-app-keys").hide();
81+
$("#node-config-fitbit-user").show();
82+
$("#node-config-input-username").val(sn);
83+
$("#node-config-fitbit-username").html(sn);
84+
}
85+
86+
function pollFitbitCredentials(e) {
87+
$.getJSON('credentials/fitbit-credentials/'+id,function(data) {
88+
if (data.username) {
89+
$("#node-config-dialog-ok").button("enable");
90+
updateFitbitScreenName(data.username);
91+
delete window.fitbitConfigNodeIntervalId;
92+
} else {
93+
window.fitbitConfigNodeIntervalId = window.setTimeout(pollFitbitCredentials,2000);
94+
}
95+
});
96+
}
97+
98+
updateFitbitAuthButton();
99+
100+
if (this.username) {
101+
updateFitbitScreenName(this.username);
102+
} else {
103+
$("#node-config-fitbit-app-keys").show();
104+
$("#node-config-fitbit-user").hide();
105+
$("#node-config-dialog-ok").button("disable");
106+
}
107+
108+
$("#node-config-start-auth").mousedown(function(e) {
109+
var key = $("#node-config-input-client_key").val();
110+
var secret = $("#node-config-input-client_secret").val();
111+
var pathname = document.location.pathname;
112+
if (pathname.slice(-1) !== "/") {
113+
pathname += "/";
114+
}
115+
var callback = encodeURIComponent(location.protocol+"//"+location.hostname+":"+location.port+pathname+"fitbit-credentials/"+id+"/auth/callback");
116+
var url = 'fitbit-credentials/'+id+'/auth?callback='+callback+'&client_key='+key+"&client_secret="+secret;
117+
$(this).attr("href",url);
118+
window.fitbitConfigNodeIntervalId = window.setTimeout(pollFitbitCredentials,2000);
119+
});
120+
$("#node-config-start-auth").click(function(e) {
121+
var key = $("#node-config-input-client_key").val();
122+
var secret = $("#node-config-input-client_secret").val();
123+
if (key === "" || secret === "") {
124+
e.preventDefault();
125+
}
126+
});
127+
128+
},
129+
oneditsave: function() {
130+
if (window.fitbitConfigNodeIntervalId) {
131+
window.clearTimeout(window.fitbitConfigNodeIntervalId);
132+
delete window.fitbitConfigNodeIntervalId;
133+
}
134+
},
135+
oneditcancel: function(adding) {
136+
if (window.fitbitConfigNodeIntervalId) {
137+
window.clearTimeout(window.fitbitConfigNodeIntervalId);
138+
delete window.fitbitConfigNodeIntervalId;
139+
}
140+
}
141+
});
142+
})();
143+
</script>
144+
145+
<script type="text/x-red" data-template-name="fitbit in">
146+
<div class="form-row">
147+
<label for="node-input-fitbit"><i class="fa fa-user"></i> Fitbit</label>
148+
<input type="text" id="node-input-fitbit">
149+
</div>
150+
<div class="form-row">
151+
<label for="node-input-dataType"><i class="fa fa-tag"></i> Type</label>
152+
<select id="node-input-dataType" style="width:125px !important">
153+
<option value="goals">goals</option>
154+
<option value="sleep">sleep</option>
155+
<option value="badges">badges</option>
156+
</select>
157+
</div>
158+
<div class="form-row">
159+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
160+
<input type="text" id="node-input-name">
161+
</div>
162+
</script>
163+
164+
<script type="text/x-red" data-help-name="fitbit in">
165+
<p>Polls <a href="http://www.fitbit.com">Fitbit</a> for new data.</p>
166+
<p>The generated messages are determined by the node <b>type</b> property
167+
as follows:</p>
168+
<dl>
169+
<dt>goals<dt>
170+
<dd>Messages are sent when a daily goal is reached.</dd>
171+
<dt>sleep</dt>
172+
<dd>Messages are sent when a new daily sleep record becomes available. The message payload contains <a
173+
href="https://wiki.fitbit.com/display/API/API-Get-Sleep"
174+
>sleep log</a> data.</dd>
175+
<dt>badges</dt>
176+
<dd>Messages are sent when a new badge is earned. The message payload contains a single badge entry from the list returned by the <a
177+
href="https://wiki.fitbit.com/display/API/API-Get-Badges"
178+
>badges API call</a>.</dd>
179+
</dl>
180+
</script>
181+
182+
<script type="text/javascript">
183+
RED.nodes.registerType('fitbit in',{
184+
category: 'social',
185+
color:"#C0DEED",
186+
defaults: {
187+
fitbit: {type:"fitbit-credentials",required:true},
188+
name: {value:""},
189+
dataType: {value:"goals"}
190+
},
191+
inputs:0,
192+
outputs:1,
193+
icon: "fitbit.png",
194+
label: function() {
195+
return this.name || ("Fitbit " + this.dataType);
196+
},
197+
oneditprepare: function() {
198+
$("#node-input-dataType").val(this.dataType);
199+
},
200+
});
201+
</script>
202+
203+
<script type="text/x-red" data-template-name="fitbit">
204+
<div class="form-row">
205+
<label for="node-input-fitbit"><i class="fa fa-user"></i> Fitbit</label>
206+
<input type="text" id="node-input-fitbit">
207+
</div>
208+
<div class="form-row">
209+
<label for="node-input-dataType"><i class="fa fa-tag"></i> Type</label>
210+
<select id="node-input-dataType" style="width:125px !important">
211+
<option value="activities">activities</option>
212+
<option value="sleep">sleep</option>
213+
<option value="badges">badges</option>
214+
</select>
215+
</div>
216+
<div class="form-row">
217+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
218+
<input type="text" id="node-input-name">
219+
</div>
220+
</script>
221+
222+
<script type="text/x-red" data-help-name="fitbit">
223+
<p>Retrieves user data from <a href="http://www.fitbit.com">Fitbit</a>.</p>
224+
<p>The message payload is determined by the node <b>type</b> property as
225+
follows:</p>
226+
<dl>
227+
<dt>activities<dt>
228+
<dd>the message payload contains <a
229+
href="https://wiki.fitbit.com/display/API/API-Get-Activities"
230+
>daily activities</a> data.</dd>
231+
<dt>sleep</dt>
232+
<dd>the message payload contains <a
233+
href="https://wiki.fitbit.com/display/API/API-Get-Sleep"
234+
>sleep log</a> data for the main sleep and the message
235+
<b>data</b> property contains the complete sleep data result.</dd>
236+
<dt>badges</dt>
237+
<dd>the message payload contains data about <a
238+
href="https://wiki.fitbit.com/display/API/API-Get-Badges"
239+
>badges</a> awarded.</dd>
240+
</dl>
241+
<p>The <b>msg.date</b> property may be set to an ISO 8601 format
242+
date (e.g. 2014-09-25) to retrieve historical data for
243+
activities and sleep log. If no date is supplied, then data for
244+
today will be retrieved. In the case of sleep, this is the data
245+
for the preceding sleep.</p>
246+
</script>
247+
248+
<script type="text/javascript">
249+
RED.nodes.registerType('fitbit',{
250+
category: 'social',
251+
color:"#C0DEED",
252+
defaults: {
253+
fitbit: {type:"fitbit-credentials",required:true},
254+
name: {value:""},
255+
dataType: {value:"activities"}
256+
},
257+
inputs:1,
258+
outputs:1,
259+
icon: "fitbit.png",
260+
align: "right",
261+
label: function() {
262+
return this.name || ("Fitbit " + this.dataType);
263+
},
264+
oneditprepare: function() {
265+
$("#node-input-dataType").val(this.dataType);
266+
},
267+
});
268+
</script>

0 commit comments

Comments
 (0)