Created
January 29, 2019 17:23
-
-
Save manekinekko/8ada9f0daf136ec6ae2c785bf4ad33c6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const fetch = require('node-fetch'); | |
const functions = require('firebase-functions'); | |
const { smarthome } = require('actions-on-google'); | |
const util = require('util'); | |
const admin = require('firebase-admin'); | |
admin.initializeApp(); | |
const firebaseRef = admin.database().ref('/'); | |
const agentUserId = '23213213131321321321'; | |
exports.auth = functions.https.onRequest((request, response) => { | |
const responseurl = util.format( | |
'%s?code=%s&state=%s', | |
decodeURIComponent(request.query.redirect_uri), | |
'xxxxxx', | |
request.query.state | |
); | |
console.log(responseurl); | |
return response.redirect(responseurl); | |
}); | |
exports.token = functions.https.onRequest((request, response) => { | |
const grantType = request.query.grant_type | |
? request.query.grant_type | |
: request.body.grant_type; | |
const secondsInDay = 86400; // 60 * 60 * 24 | |
const HTTP_STATUS_OK = 200; | |
console.log(`Grant type ${grantType}`); | |
let obj; | |
if (grantType === 'authorization_code') { | |
obj = { | |
token_type: 'bearer', | |
access_token: '123access', | |
refresh_token: '123refresh', | |
expires_in: secondsInDay | |
}; | |
} else if (grantType === 'refresh_token') { | |
obj = { | |
token_type: 'bearer', | |
access_token: '123access', | |
expires_in: secondsInDay | |
}; | |
} | |
response.status(HTTP_STATUS_OK).json(obj); | |
}); | |
let jwt; | |
try { | |
jwt = require('./key.json'); | |
} catch (e) { | |
console.warn('Service account key is not found'); | |
console.warn('Report state will be unavailable'); | |
} | |
const queryFirebase = deviceId => | |
firebaseRef | |
.child(deviceId) | |
.once('value') | |
.then(snapshot => { | |
const snapshotVal = snapshot.val(); | |
return { | |
on: snapshotVal.on, | |
online: snapshotVal.online, | |
}; | |
}); | |
const queryDevice = deviceId => | |
queryFirebase(deviceId).then(data => ({ | |
on: data.on | |
})); | |
const app = smarthome({ | |
debug: true, | |
key: jwt.key, | |
jwt: jwt | |
}); | |
app.onSync((body, headers) => { | |
return { | |
requestId: body.requestId, | |
payload: { | |
agentUserId, | |
devices: [ | |
{ | |
id: 'standing-desk-123', | |
type: 'action.devices.types.SWITCH', | |
traits: ['action.devices.traits.OnOff'], | |
name: { | |
defaultNames: ['My Standing Desk'], | |
name: 'Standing Desk', | |
nicknames: ['Standing Desk'] | |
}, | |
deviceInfo: { | |
manufacturer: 'Wassim Chegham', | |
model: '123456789', | |
hwVersion: '1.0', | |
swVersion: '1.0' | |
} | |
} | |
] | |
} | |
}; | |
}); | |
app.onQuery(body => { | |
const { requestId } = body; | |
const device = body.inputs.pop().payload.devices.pop(); | |
const deviceId = device.id; | |
return queryDevice(deviceId).then(data => { | |
return { | |
requestId, | |
payload: { | |
devices: { | |
[deviceId]: data | |
} | |
} | |
}; | |
}); | |
}); | |
app.onExecute((body, headers) => { | |
const { requestId } = body; | |
const commands = body.inputs.pop().payload.commands; | |
const command = commands.pop(); | |
const device = command.devices.pop(); | |
const deviceId = device.id; | |
const exec = command.execution.pop(); | |
const { params } = exec; | |
console.log(body); | |
firebaseRef | |
.child(deviceId) | |
.child('state') | |
.update({ | |
on: params.on | |
}); | |
return { | |
requestId, | |
payload: { | |
commands: [ | |
{ | |
ids: [deviceId], | |
status: 'SUCCESS', | |
states: { | |
online: true | |
} | |
} | |
] | |
} | |
}; | |
}); | |
app.onDisconnect((body, headers) => { | |
return {}; | |
}); | |
exports.smarthome = functions.https.onRequest(app); | |
exports.requestsync = functions.https.onRequest((request, response) => { | |
return app.requestSync(agentUserId) | |
.then((res) => { | |
console.log('Request sync was successful', res); | |
}) | |
.catch((res) => { | |
console.error('Request sync failed', res); | |
}); | |
}); | |
/** | |
* Send a REPORT STATE call to the homegraph when data for any device id | |
* has been changed. | |
*/ | |
exports.reportstate = functions.database.ref('{deviceId}/state').onWrite(event => { | |
console.info('Firebase write event triggered this cloud function'); | |
if (!app.jwt) { | |
console.warn('Service account key is not configured'); | |
console.warn('Report state is unavailable'); | |
return; | |
} | |
const snapshotVal = event.after.val(); | |
console.log('snapshotVal', snapshotVal); | |
const mode = snapshotVal.on == true ? '3' : '1'; | |
return fetch(`https://wassimchegham.ngrok.io/mode/${mode}`) | |
.then(res => { | |
console.log(res.ok, res.status, res.statusText, res.headers.raw(), res.headers.get('content-type')); | |
return res; | |
}) | |
.then(res => (res.status == '404' ? null : res.json())) | |
.then(json => { | |
if (json) { | |
return { | |
requestId: 'xxxxxxxxxx', | |
agentUserId, | |
payload: { | |
devices: { | |
states: { | |
[event.params.deviceId]: { | |
on: snapshotVal.on | |
} | |
} | |
} | |
} | |
}; | |
} else { | |
throw new Error('deviceOffline'); | |
} | |
}) | |
.then(postData => app.reportState(postData)) | |
.then(data => { | |
console.log('Report state came back'); | |
console.info(data); | |
}) | |
.catch((res) => { | |
return { | |
requestId: 'xxxxxxxxxx', | |
agentUserId, | |
payload: { | |
errorCode: 'deviceOffline' | |
} | |
}; | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment