Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save manekinekko/8ada9f0daf136ec6ae2c785bf4ad33c6 to your computer and use it in GitHub Desktop.
Save manekinekko/8ada9f0daf136ec6ae2c785bf4ad33c6 to your computer and use it in GitHub Desktop.
'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