commit
6687c063a0
@ -0,0 +1,7 @@
|
|||||||
|
#Personl TestAPI
|
||||||
|
#FITBIT_CLIENT_ID=23QX5D
|
||||||
|
#FITBIT_CLIENT_SECRET=801d6a43fb2fe015b10362376928b617
|
||||||
|
|
||||||
|
#Server TestAPI2
|
||||||
|
FITBIT_CLIENT_ID=23QX94
|
||||||
|
FITBIT_CLIENT_SECRET=1418c9846a17b734098ac6c49aab235f
|
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "fitbit",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node ./src/main.js",
|
||||||
|
"start:dev": "npx nodemon -w ./src ./src/main.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^16.0.3",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"moment": "^2.29.4",
|
||||||
|
"node-fetch": "^2.6.11"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^2.0.22"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
const crypto = require('crypto')
|
||||||
|
const express = require('express')
|
||||||
|
const fetch = require('node-fetch')
|
||||||
|
var moment = require('moment');
|
||||||
|
|
||||||
|
require('dotenv').config();
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
main()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
try {
|
||||||
|
const router = express()
|
||||||
|
const verifier = base64UrlEncode(crypto.randomBytes(64)) // <1>
|
||||||
|
const challenge = base64UrlEncode(sha256Hash(Buffer.from(verifier))) // <2>
|
||||||
|
console.log('env ', process.env.FITBIT_CLIENT_ID, process.env.FITBIT_CLIENT_SECRET)
|
||||||
|
|
||||||
|
router.get('/signin', (req, res) => { // <3>
|
||||||
|
const search = '?' + new URLSearchParams({
|
||||||
|
'client_id': process.env.FITBIT_CLIENT_ID,
|
||||||
|
'response_type': 'code',
|
||||||
|
'code_challenge': challenge,
|
||||||
|
'code_challenge_method': 'S256',
|
||||||
|
// 'scope': 'heartrate',
|
||||||
|
'scope': 'activity',
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const url = 'https://www.fitbit.com/oauth2/authorize' + search
|
||||||
|
res.redirect(url)
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get('/callback', async (req, res, next) => { // <4>
|
||||||
|
try {
|
||||||
|
const user = process.env.FITBIT_CLIENT_ID
|
||||||
|
const pass = process.env.FITBIT_CLIENT_SECRET
|
||||||
|
const credentials = Buffer.from(`${user}:${pass}`).toString('base64')
|
||||||
|
const tokenUrl = 'https://api.fitbit.com/oauth2/token'
|
||||||
|
const tokenResponse = await fetch(tokenUrl, { // <5>
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Basic ${credentials}`,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: new URLSearchParams({
|
||||||
|
'client_id': process.env.FITBIT_CLIENT_ID,
|
||||||
|
'code': req.query.code,
|
||||||
|
'code_verifier': verifier,
|
||||||
|
'grant_type': 'authorization_code',
|
||||||
|
}).toString(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const tokenBody = await tokenResponse.json()
|
||||||
|
console.log('tokenBody', tokenBody)
|
||||||
|
|
||||||
|
if (tokenBody.errors) { // <6>
|
||||||
|
console.error(tokenBody.errors[0].message)
|
||||||
|
res.status(500).end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = '-'
|
||||||
|
const date = 'today'
|
||||||
|
const detailLevel = '1sec'
|
||||||
|
// const dataUrl = 'https://api.fitbit.com/' + [
|
||||||
|
// '1',
|
||||||
|
// 'user',
|
||||||
|
// userId,
|
||||||
|
// 'activities',
|
||||||
|
// 'heart',
|
||||||
|
// 'date',
|
||||||
|
// date,
|
||||||
|
// '1d',
|
||||||
|
// `${detailLevel}.json`
|
||||||
|
// ].join('/')
|
||||||
|
const today = moment();
|
||||||
|
const dataUrl = 'https://api.fitbit.com/' + [
|
||||||
|
'1',
|
||||||
|
'user',
|
||||||
|
userId,
|
||||||
|
'activities',
|
||||||
|
'date',
|
||||||
|
`${today.format('YYYY-MM-D')}.json`
|
||||||
|
].join('/')
|
||||||
|
console.log('URL ', dataUrl)
|
||||||
|
|
||||||
|
const dataResponse = await fetch(dataUrl, { // <7>
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${tokenBody['access_token']}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const dataBody = await dataResponse.json()
|
||||||
|
|
||||||
|
if (dataBody.errors) { // <8>
|
||||||
|
console.error(dataBody.errors[0].message)
|
||||||
|
res.status(500).end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res.type('text/plain') // <9>
|
||||||
|
.send(JSON.stringify(dataBody, null, 2))
|
||||||
|
} catch (err) {
|
||||||
|
next(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get('/show', async(req, res) => { // <3>
|
||||||
|
const today = moment();
|
||||||
|
var result = ''
|
||||||
|
var userId = '55QCL4';
|
||||||
|
var userToken = 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyM1FYOTQiLCJzdWIiOiI1NVFDTDQiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyYWN0IiwiZXhwIjoxNjg1NzI1OTcyLCJpYXQiOjE2ODU2OTcxNzJ9.k94QyIMqoBOfyqAzvkjeFkn7SFmKOae5l4Y4AqRSzCg';
|
||||||
|
var dataUrl = 'https://api.fitbit.com/' + [
|
||||||
|
'1',
|
||||||
|
'user',
|
||||||
|
userId,
|
||||||
|
'activities',
|
||||||
|
'date',
|
||||||
|
`${today.format('YYYY-MM-D')}.json`
|
||||||
|
].join('/')
|
||||||
|
console.log('URL ', dataUrl)
|
||||||
|
|
||||||
|
var dataResponse = await fetch(dataUrl, { // <7>
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${userToken}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
var dataBody = await dataResponse.json()
|
||||||
|
|
||||||
|
if (dataBody.errors) { // <8>
|
||||||
|
console.error(dataBody.errors[0].message)
|
||||||
|
res.status(500).end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var string = JSON.stringify(dataBody, null, 2);
|
||||||
|
var data = JSON.parse(string);
|
||||||
|
var steps = data.summary['steps'];
|
||||||
|
console.log(steps);
|
||||||
|
result = today.toDate()+ ' \nSchritte Marcus '+ steps ;
|
||||||
|
// res.type('text/plain') // <9>
|
||||||
|
// .send('Steps Marcus '+ steps ) //dataBody.summary.steps
|
||||||
|
|
||||||
|
userId = '7NBCBG';
|
||||||
|
userToken = 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyM1FYOTQiLCJzdWIiOiI3TkJDQkciLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyYWN0IiwiZXhwIjoxNjg1NzM2MjM2LCJpYXQiOjE2ODU3MDc0MzZ9.5uAKWIeaLHDrQWTQ7099N-QkrpHUqAIfvtXEIZcoaUY';
|
||||||
|
dataUrl = 'https://api.fitbit.com/' + [
|
||||||
|
'1',
|
||||||
|
'user',
|
||||||
|
userId,
|
||||||
|
'activities',
|
||||||
|
'date',
|
||||||
|
`${today.format('YYYY-MM-D')}.json`
|
||||||
|
].join('/')
|
||||||
|
console.log('URL ', dataUrl)
|
||||||
|
|
||||||
|
dataResponse = await fetch(dataUrl, { // <7>
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${userToken}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
dataBody = await dataResponse.json()
|
||||||
|
|
||||||
|
if (dataBody.errors) { // <8>
|
||||||
|
console.error(dataBody.errors[0].message)
|
||||||
|
res.status(500).end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
string = JSON.stringify(dataBody, null, 2);
|
||||||
|
data = JSON.parse(string);
|
||||||
|
steps = data.summary['steps'];
|
||||||
|
console.log(steps)
|
||||||
|
result = result + '\n' + 'Schritte Ute '+ steps
|
||||||
|
res.type('text/plain') // <9>
|
||||||
|
// .send('Steps Ute'+ steps ) //dataBody.summary.steps
|
||||||
|
.send(result)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
router.listen(3000)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function base64UrlEncode (buffer) { // <10>
|
||||||
|
return buffer.toString('base64')
|
||||||
|
.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/=/g, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
function sha256Hash (buffer) { // <11>
|
||||||
|
const hash = crypto.createHash('sha256')
|
||||||
|
|
||||||
|
hash.update(buffer)
|
||||||
|
return hash.digest()
|
||||||
|
}
|
Loading…
Reference in new issue