From 40b538589bd3352afe16fdb98b9f06b7b6ce590e Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 13 Mar 2020 11:58:15 +0100 Subject: [PATCH 1/5] updated to comply with new api version --- plejd/api.js | 126 ++++++++++++++++++++++++++++----------- plejd/config.json | 2 +- plejd/main.js | 149 +++++++++++++++++++++++----------------------- 3 files changed, 167 insertions(+), 110 deletions(-) diff --git a/plejd/api.js b/plejd/api.js index 3caecc8..9643b96 100644 --- a/plejd/api.js +++ b/plejd/api.js @@ -5,7 +5,8 @@ const _ = require('lodash'); API_APP_ID = 'zHtVqXt8k4yFyk2QGmgp48D9xZr2G94xWYnF4dak'; API_BASE_URL = 'https://cloud.plejd.com/parse/'; API_LOGIN_URL = 'login'; -API_SITES_URL = 'functions/getSites'; +API_SITE_LIST_URL = 'functions/getSiteList'; +API_SITE_DETAILS_URL = 'functions/getSiteById'; // #region logging let debug = ''; @@ -56,31 +57,41 @@ class PlejdApi extends EventEmitter { } }); - logger('sending POST to ' + API_BASE_URL + API_LOGIN_URL); + return new Promise((resolve, reject) => { + logger('sending POST to ' + API_BASE_URL + API_LOGIN_URL); - instance.post( - API_LOGIN_URL, - { - 'username': this.username, - 'password': this.password - }) - .then((response) => { - console.log('plejd-api: got session token response'); - self.sessionToken = response.data.sessionToken; - self.emit('loggedIn'); - }) - .catch((error) => { - if (error.response.status === 400) { - console.log('error: server returned status 400. probably invalid credentials, please verify.'); - } - else { - console.log('error: unable to retrieve session token response: ' + error); - } - }); + instance.post( + API_LOGIN_URL, + { + 'username': this.username, + 'password': this.password + }) + .then((response) => { + console.log('plejd-api: got session token response'); + self.sessionToken = response.data.sessionToken; + + if (!self.sessionToken) { + console.log('plejd-api: error: no session token received'); + reject('no session token received.'); + } + + resolve(); + }) + .catch((error) => { + if (error.response.status === 400) { + console.log('error: server returned status 400. probably invalid credentials, please verify.'); + } + else { + console.log('error: unable to retrieve session token response: ' + error); + } + + reject('unable to retrieve session token response: ' + error); + }); + }); } - getCryptoKey(callback) { - console.log('plejd-api: getCryptoKey()'); + getSites() { + console.log('plejd-api: getSites()'); const self = this; const instance = axios.create({ @@ -92,20 +103,65 @@ class PlejdApi extends EventEmitter { } }); - logger('sending POST to ' + API_BASE_URL + API_SITES_URL); + return new Promise((resolve, reject) => { + logger('sending POST to ' + API_BASE_URL + API_SITE_LIST_URL); - instance.post(API_SITES_URL) - .then((response) => { - console.log('plejd-api: got sites response'); - self.site = response.data.result.find(x => x.site.title == self.siteName); - self.cryptoKey = self.site.plejdMesh.cryptoKey; + instance.post(API_SITE_LIST_URL) + .then((response) => { + console.log('plejd-api: got site list response'); + const site = response.data.result.find(x => x.site.title == self.siteName); - this.emit('ready', self.cryptoKey, self.site); - }) - .catch((error) => { - console.log('error: unable to retrieve the crypto key. error: ' + error); - return Promise.reject('unable to retrieve the crypto key. error: ' + error); - }); + if (!site) { + console.log('plejd-api: error: failed to find a site named ' + self.siteName); + reject('failed to find a site named ' + self.siteName); + return; + } + + resolve(site); + }) + .catch((error) => { + console.log('plejd-api: error: unable to retrieve list of sites. error: ' + error); + return reject('plejd-api: unable to retrieve list of sites. error: ' + error); + }); + }); + } + + getSite(siteId) { + console.log('plejd-api: getSites()'); + const self = this; + + const instance = axios.create({ + baseURL: API_BASE_URL, + headers: { + 'X-Parse-Application-Id': API_APP_ID, + 'X-Parse-Session-Token': this.sessionToken, + 'Content-Type': 'application/json' + } + }); + + return new Promise((resolve, reject) => { + logger('sending POST to ' + API_BASE_URL + API_SITE_DETAILS_URL); + + instance.post(API_SITE_DETAILS_URL, { siteId: siteId }) + .then((response) => { + console.log('plejd-api: got site details response'); + if (response.data.result.length === 0) { + const msg = 'no site with ID ' + siteId + ' was found.'; + console.log('plejd-api: error: ' + msg); + reject(msg); + return; + } + + self.site = response.data.result[0]; + self.cryptoKey = self.site.plejdMesh.cryptoKey; + + resolve(self.cryptoKey); + }) + .catch((error) => { + console.log('plejd-api: error: unable to retrieve the crypto key. error: ' + error); + return reject('plejd-api: unable to retrieve the crypto key. error: ' + error); + }); + }); } getDevices() { diff --git a/plejd/config.json b/plejd/config.json index edff1ed..3461e30 100644 --- a/plejd/config.json +++ b/plejd/config.json @@ -1,6 +1,6 @@ { "name": "Plejd", - "version": "0.4.2", + "version": "0.4.3", "slug": "plejd", "description": "Adds support for the Swedish home automation devices from Plejd.", "url": "https://github.com/icanos/hassio-plejd/", diff --git a/plejd/main.js b/plejd/main.js index 4f1f538..0b0e2e8 100644 --- a/plejd/main.js +++ b/plejd/main.js @@ -4,7 +4,7 @@ const fs = require('fs'); const PlejdService = require('./ble.bluez'); const SceneManager = require('./scene.manager'); -const version = "0.4.2"; +const version = "0.4.3"; async function main() { console.log('starting Plejd add-on v. ' + version); @@ -19,96 +19,97 @@ async function main() { const plejdApi = new api.PlejdApi(config.site, config.username, config.password); const client = new mqtt.MqttClient(config.mqttBroker, config.mqttUsername, config.mqttPassword); - plejdApi.once('loggedIn', () => { - plejdApi.on('ready', (cryptoKey, site) => { - const devices = plejdApi.getDevices(); + plejdApi.login().then(() => { + // load all sites and find the one that we want (from config) + plejdApi.getSites().then((site) => { + // load the site and retrieve the crypto key + plejdApi.getSite(site.site.siteId).then((cryptoKey) => { + // parse all devices from the API + const devices = plejdApi.getDevices(); - client.on('connected', () => { - console.log('plejd-mqtt: connected to mqtt.'); - client.discover(devices); - }); + client.on('connected', () => { + console.log('plejd-mqtt: connected to mqtt.'); + client.discover(devices); + }); - client.init(); + client.init(); - // init the BLE interface - const sceneManager = new SceneManager(site, devices); - const plejd = new PlejdService(cryptoKey, devices, sceneManager, config.connectionTimeout, config.writeQueueWaitTime, true); - plejd.on('connectFailed', () => { - console.log('plejd-ble: were unable to connect, will retry connection in 10 seconds.'); - setTimeout(() => { - plejd.init(); - }, 10000); - }); + // init the BLE interface + const sceneManager = new SceneManager(site, devices); + const plejd = new PlejdService(cryptoKey, devices, sceneManager, config.connectionTimeout, config.writeQueueWaitTime, true); + plejd.on('connectFailed', () => { + console.log('plejd-ble: were unable to connect, will retry connection in 10 seconds.'); + setTimeout(() => { + plejd.init(); + }, 10000); + }); - plejd.init(); + plejd.init(); - plejd.on('authenticated', () => { - console.log('plejd: connected via bluetooth.'); - }); + plejd.on('authenticated', () => { + console.log('plejd: connected via bluetooth.'); + }); - // subscribe to changes from Plejd - plejd.on('stateChanged', (deviceId, command) => { - client.updateState(deviceId, command); - }); + // subscribe to changes from Plejd + plejd.on('stateChanged', (deviceId, command) => { + client.updateState(deviceId, command); + }); - plejd.on('sceneTriggered', (deviceId, scene) => { - client.sceneTriggered(scene); - }); + plejd.on('sceneTriggered', (deviceId, scene) => { + client.sceneTriggered(scene); + }); - // subscribe to changes from HA - client.on('stateChanged', (device, command) => { - const deviceId = device.id; + // subscribe to changes from HA + client.on('stateChanged', (device, command) => { + const deviceId = device.id; - if (device.typeName === 'Scene') { - // we're triggering a scene, lets do that and jump out. - // since scenes aren't "real" devices. - plejd.triggerScene(device.id); - return; - } + if (device.typeName === 'Scene') { + // we're triggering a scene, lets do that and jump out. + // since scenes aren't "real" devices. + plejd.triggerScene(device.id); + return; + } - let state = 'OFF'; - let commandObj = {}; + let state = 'OFF'; + let commandObj = {}; - if (typeof command === 'string') { - // switch command - state = command; - commandObj = { state: state }; + if (typeof command === 'string') { + // switch command + state = command; + commandObj = { state: state }; - // since the switch doesn't get any updates on whether it's on or not, - // we fake this by directly send the updateState back to HA in order for - // it to change state. - client.updateState(deviceId, { state: state === 'ON' ? 1 : 0 }); - } - else { - state = command.state; - commandObj = command; - } + // since the switch doesn't get any updates on whether it's on or not, + // we fake this by directly send the updateState back to HA in order for + // it to change state. + client.updateState(deviceId, { state: state === 'ON' ? 1 : 0 }); + } + else { + state = command.state; + commandObj = command; + } - if (state === 'ON') { - plejd.turnOn(deviceId, commandObj); - } - else { - plejd.turnOff(deviceId, commandObj); - } - }); + if (state === 'ON') { + plejd.turnOn(deviceId, commandObj); + } + else { + plejd.turnOff(deviceId, commandObj); + } + }); - client.on('settingsChanged', (settings) => { - if (settings.module === 'mqtt') { - client.updateSettings(settings); - } - else if (settings.module === 'ble') { - plejd.updateSettings(settings); - } - else if (settings.module === 'api') { - plejdApi.updateSettings(settings); - } + client.on('settingsChanged', (settings) => { + if (settings.module === 'mqtt') { + client.updateSettings(settings); + } + else if (settings.module === 'ble') { + plejd.updateSettings(settings); + } + else if (settings.module === 'api') { + plejdApi.updateSettings(settings); + } + }); }); }); - - plejdApi.getCryptoKey(); }); - - plejdApi.login(); } main(); \ No newline at end of file From 9ece2b3cf3da0f0e4890dc2f571dff3751ce314a Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 13 Mar 2020 12:00:46 +0100 Subject: [PATCH 2/5] debug --- plejd/api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plejd/api.js b/plejd/api.js index 9643b96..bcbcf7b 100644 --- a/plejd/api.js +++ b/plejd/api.js @@ -110,6 +110,7 @@ class PlejdApi extends EventEmitter { .then((response) => { console.log('plejd-api: got site list response'); const site = response.data.result.find(x => x.site.title == self.siteName); + console.log(site); if (!site) { console.log('plejd-api: error: failed to find a site named ' + self.siteName); From 35bbfbe7462c2bfd04b923a8940e94ccc33b7f92 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 13 Mar 2020 12:01:22 +0100 Subject: [PATCH 3/5] debug --- plejd/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plejd/api.js b/plejd/api.js index bcbcf7b..6d5b875 100644 --- a/plejd/api.js +++ b/plejd/api.js @@ -110,7 +110,6 @@ class PlejdApi extends EventEmitter { .then((response) => { console.log('plejd-api: got site list response'); const site = response.data.result.find(x => x.site.title == self.siteName); - console.log(site); if (!site) { console.log('plejd-api: error: failed to find a site named ' + self.siteName); @@ -154,6 +153,7 @@ class PlejdApi extends EventEmitter { } self.site = response.data.result[0]; + console.log(self.site); self.cryptoKey = self.site.plejdMesh.cryptoKey; resolve(self.cryptoKey); From 7260de46cad1a6953c4592a9b34726cac604e2e9 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 13 Mar 2020 12:02:56 +0100 Subject: [PATCH 4/5] fixed wrong reference in scene manager --- plejd/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plejd/main.js b/plejd/main.js index 0b0e2e8..3d0ba33 100644 --- a/plejd/main.js +++ b/plejd/main.js @@ -35,7 +35,7 @@ async function main() { client.init(); // init the BLE interface - const sceneManager = new SceneManager(site, devices); + const sceneManager = new SceneManager(plejdApi.site, devices); const plejd = new PlejdService(cryptoKey, devices, sceneManager, config.connectionTimeout, config.writeQueueWaitTime, true); plejd.on('connectFailed', () => { console.log('plejd-ble: were unable to connect, will retry connection in 10 seconds.'); From f2a0da5ae885f5fcb75d7b4fede4d640c220bf89 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 13 Mar 2020 12:03:57 +0100 Subject: [PATCH 5/5] removed debugging --- plejd/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plejd/api.js b/plejd/api.js index 6d5b875..9643b96 100644 --- a/plejd/api.js +++ b/plejd/api.js @@ -153,7 +153,6 @@ class PlejdApi extends EventEmitter { } self.site = response.data.result[0]; - console.log(self.site); self.cryptoKey = self.site.plejdMesh.cryptoKey; resolve(self.cryptoKey);