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