Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save manekinekko/8ada9f0daf136ec6ae2c785bf4ad33c6 to your computer and use it in GitHub Desktop.

Select an option

Save manekinekko/8ada9f0daf136ec6ae2c785bf4ad33c6 to your computer and use it in GitHub Desktop.

Revisions

  1. manekinekko created this gist Jan 29, 2019.
    230 changes: 230 additions & 0 deletions desk-controller-assistant-aog-home-control-full.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,230 @@
    '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'
    }
    };
    });
    });