require('dotenv').config();
const {
v4: uuid
} = require('uuid');
const mysql = require('mysql');
const v3 = require('node-hue-api').v3;
const axios = require('axios');
const utils = require('./server/utils');
const hue_auth = require('./server/utils/hue/auth');
// Values for the ClientId, ClientSecret and AppId from the Hue Remote Application you create in your developer account.
const APP_ID = 'smart-home-server';
const remoteBootstrap = v3.api.createRemote(
process.env.HUE_CLIENT_ID,
process.env.HUE_CLIENT_SECRET
);
global.MYSQL_POOL = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
user: process.env.SQL_USER,
password: process.env.SQL_PASS,
database: 'smart_home'
});
console.log("Start Philips Hue authentication...");
// A state value you can use to validate the Callback URL results with, it should not really be hardcoded, but should
// be dynamically generated.
let state;
utils.query("SELECT state from hue_auth").then(function(rows) {
if (rows.length) {
state = rows[0].state;
if (!state) {
state = uuid();
console.log("New transaction state:", state);
} else {
console.log("Transaction state restored:", state);
}
return "UPDATE";
} else {
state = uuid();
return "INSERT INTO";
}
}).then(function(command) {
return utils.query(`${command} hue_auth SET ?`, {
state: state
});
}).then(function() {
return utils.query("SELECT auth_code FROM hue_auth");
}).then(function(rows) {
return new Promise(function(resolve, reject) {
let authorizationCode;
if (rows.length) {
authorizationCode = rows[0].auth_code;
}
if (authorizationCode) {
resolve(authorizationCode);
} else {
reject(
"Generate an authorization code for your application using this URL:\n\n" +
remoteBootstrap.getAuthCodeUrl('node-hue-api-remote', APP_ID, state) + "\n"
);
}
});
}).then(function(authorizationCode) {
// Exchange the code for tokens and connect to the Remote Hue API
return remoteBootstrap.connectWithCode(authorizationCode);
}).then(function(api) {
console.log('Successfully validated authorization code and exchanged for tokens');
const remoteCredentials = api.remote.getRemoteAccessCredentials();
return hue_auth.store_auth({
access_token: remoteCredentials.tokens.access.value,
access_token_expires: remoteCredentials.tokens.access.expiresAt,
refresh_token: remoteCredentials.tokens.refresh.value,
refresh_token_expires: remoteCredentials.tokens.refresh.expiresAt,
username: remoteCredentials.username,
auth_code: null
});
}).then(function() {
console.log("Philips Hue authentication obtained");
return axios.post(`http://localhost:${process.env.PORT || 4669}/hue/reauthenticate`, {
state: state
});
}).then(function(response) {
if (response.data.status === "ok") {
console.log("Smarthome Server successfully reauthenticated with Philips Hue");
} else {
console.log("Smarthome Server could not automatically reauthenticate with Philips Hue\n", response.data.message);
}
return utils.query("UPDATE hue_auth SET ?", {
state: null
});
}).then(function() {
console.log("Philips Hue authentication successful");
}).catch(function(err) {
console.log('Philips Hue authentication unsuccessful. Reason:\n', err);
return utils.query("DELETE FROM hue_auth");
}).finally(function() {
process.exit(0);
});