From d335f9c1e0ed1014b9572024696303850bdce37f Mon Sep 17 00:00:00 2001 From: Peter Murray <681306+peter-murray@users.noreply.github.com> Date: Mon, 18 Nov 2019 18:45:26 +0000 Subject: [PATCH 1/8] Temporary fix for issue #147 until I can get version information for affected bridge --- lib/api/Users.js | 5 +++-- lib/api/Users.test.js | 13 ++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/api/Users.js b/lib/api/Users.js index 88dd0df..6b8425b 100644 --- a/lib/api/Users.js +++ b/lib/api/Users.js @@ -45,8 +45,9 @@ module.exports = class Users extends ApiDefinition { }); } - createUser(appName, deviceName) { - return this.execute(configurationApi.createUser, {appName: appName, deviceName: deviceName, generateKey: true}); + createUser(appName, deviceName, noClientKey) { + //TODO perform validation on the bridge config to see if it supports the generateKey parameters once we have a known version number + return this.execute(configurationApi.createUser, {appName: appName, deviceName: deviceName, generateKey: !noClientKey}); } deleteUser(username) { diff --git a/lib/api/Users.test.js b/lib/api/Users.test.js index 99d0a15..b2ed0a0 100644 --- a/lib/api/Users.test.js +++ b/lib/api/Users.test.js @@ -29,7 +29,8 @@ describe('Hue API #users', () => { it('should create a user when the link button has been pressed', async () => { const user = await unauthenticatedHue.users.createUser('node-hue-api', 'delete-tests'); - expect(user).to.have.length.greaterThan(39); + expect(user).to.have.property('username').to.have.length.greaterThan(39); + expect(user).to.have.property('clientkey'); createdUser = user; }); @@ -47,6 +48,16 @@ describe('Hue API #users', () => { }); + describe('#createUser() no clientkey', () => { + + it('should create a user when the link button has been pressed', async () => { + const user = await unauthenticatedHue.users.createUser('node-hue-api', 'delete-tests', true); + expect(user).to.have.property('username').to.have.length.greaterThan(39); + expect(user).to.not.have.property('clientkey'); + }); + }); + + describe.skip('#deleteUser()', () => { // it('should delete a user that we created', async () => { From c030b3e118c69033961b9b8c52312358eab6b8aa Mon Sep 17 00:00:00 2001 From: Peter Murray <681306+peter-murray@users.noreply.github.com> Date: Mon, 18 Nov 2019 18:46:56 +0000 Subject: [PATCH 2/8] 3.4.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 25c8499..087b092 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "node-hue-api", - "version": "3.4.1", + "version": "3.4.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a870887..4c04b64 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-hue-api", "description": "Philips Hue API Library for Node.js", - "version": "3.4.1", + "version": "3.4.2", "author": "Peter Murray ", "contributors": [ { From b95ae99a02c0e600f4e52902a50163e0f1518774 Mon Sep 17 00:00:00 2001 From: Peter Murray <681306+peter-murray@users.noreply.github.com> Date: Mon, 18 Nov 2019 18:48:05 +0000 Subject: [PATCH 3/8] Release 3.4.2 --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 7df3af0..26746dc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ # Change Log +## 3.4.2 +- Temporary fix for older bridges that do not support the entertainment API. Issue #147 + ## 3.4.1 - Fixing issue with the lookup for the Hue motion sensor, issue #146 From 251bec703bf39e8f13db32afbaa1d5af7d6f1b86 Mon Sep 17 00:00:00 2001 From: Peter Murray <681306+peter-murray@users.noreply.github.com> Date: Tue, 19 Nov 2019 14:36:58 +0000 Subject: [PATCH 4/8] Long term fix for generateclientkey parameter issue on older bridges, now exposing the bridge model number so that library can correctly pass the parameters to user creation based off it, Fixes issue #147 --- lib/api/Api.js | 43 +++++++++++++++---------- lib/api/Configuration.js | 4 +++ lib/api/Users.js | 11 +++++-- lib/api/Users.test.js | 23 +++++++------ lib/api/http/endpoints/configuration.js | 18 ++++++++++- lib/api/stateCache.js | 12 +++++-- 6 files changed, 76 insertions(+), 35 deletions(-) diff --git a/lib/api/Api.js b/lib/api/Api.js index b16e310..453f391 100644 --- a/lib/api/Api.js +++ b/lib/api/Api.js @@ -53,7 +53,9 @@ module.exports = class Api { const self = this; if (self.isSyncing()) { - return self._syncPromise.then(() => {return self._state;}); + return self._syncPromise.then(() => { + return self._state; + }); } else { return Promise.resolve(self._state); } @@ -70,27 +72,32 @@ module.exports = class Api { syncWithBridge() { const self = this; - // We can only sync if there is a username passed to us, which will not be the case if we are creating the user - // first. - if (self._config.username) { - if (!self.isSyncing()) { - self._syncPromise = self.configuration.getAll() - .then(data => { - self._syncPromise = null; - self._state = new StateCache(data); - self._lastSyncTime = new Date().getTime(); - }) - .catch(() => { - self._syncPromise = null; - }); + if (!self.isSyncing()) { + if (self._config.username) { + // We can only sync if there is a username passed to us, which will not be the case if we are creating the user + // first. + self._syncPromise = self.configuration.getAll(); + } else { + // We can only obtain the open config when no user is passed in + self._syncPromise = self.configuration.getUnauthenticatedConfig(); } + + self._syncPromise = self._syncPromise.then(data => { + self._syncPromise = null; + self._state = new StateCache(data); + self._lastSyncTime = new Date().getTime(); + }) + .catch(() => { + self._syncPromise = null; + }); } } getLightDefinition(id) { - return this.getCachedState().then(() => { - return this._state.getLight(id); - }); + return this.getCachedState() + .then(() => { + return this._state.getLight(id); + }); } _getConfig() { @@ -104,4 +111,6 @@ module.exports = class Api { _getRemote() { return this._config.remote; } + + }; \ No newline at end of file diff --git a/lib/api/Configuration.js b/lib/api/Configuration.js index a0e21fa..6d35eec 100644 --- a/lib/api/Configuration.js +++ b/lib/api/Configuration.js @@ -15,6 +15,10 @@ module.exports = class Configuration extends ApiDefinition { return this.execute(configurationApi.getFullState); } + getUnauthenticatedConfig() { + return this.execute(configurationApi.getUnauthenticatedConfig); + } + update(data) { return this.execute(configurationApi.updateConfiguration, data); } diff --git a/lib/api/Users.js b/lib/api/Users.js index 6b8425b..8c99d57 100644 --- a/lib/api/Users.js +++ b/lib/api/Users.js @@ -45,9 +45,14 @@ module.exports = class Users extends ApiDefinition { }); } - createUser(appName, deviceName, noClientKey) { - //TODO perform validation on the bridge config to see if it supports the generateKey parameters once we have a known version number - return this.execute(configurationApi.createUser, {appName: appName, deviceName: deviceName, generateKey: !noClientKey}); + createUser(appName, deviceName) { + return this.hueApi.getCachedState() + .then(state => { + //TODO may need to combine the modelid and API version, but am assuming that all newer bridges are kept up to + // date, as do not know the specific version number of the introduction of the generateclientkey parameter. + const oldBridge = state.modelid === 'BSB001'; + return this.execute(configurationApi.createUser, {appName: appName, deviceName: deviceName, generateKey: !oldBridge}); + }); } deleteUser(username) { diff --git a/lib/api/Users.test.js b/lib/api/Users.test.js index b2ed0a0..0d964de 100644 --- a/lib/api/Users.test.js +++ b/lib/api/Users.test.js @@ -37,9 +37,8 @@ describe('Hue API #users', () => { it('should not create a new user when link button not pressed', async () => { try { - const user = await unauthenticatedHue.users.createUser('node-hue-api', 'node-hue-api-tests'); - console.log(`Created user: ${user}`); - expect.fail('should not ger here unless the link button was pressed'); + await unauthenticatedHue.users.createUser('node-hue-api', 'node-hue-api-tests'); + expect.fail('should not get here unless the link button was pressed'); } catch (err) { expect(err).to.be.instanceof(ApiError); expect(err.getHueErrorType()).to.equal(101); @@ -47,15 +46,15 @@ describe('Hue API #users', () => { }); }); - - describe('#createUser() no clientkey', () => { - - it('should create a user when the link button has been pressed', async () => { - const user = await unauthenticatedHue.users.createUser('node-hue-api', 'delete-tests', true); - expect(user).to.have.property('username').to.have.length.greaterThan(39); - expect(user).to.not.have.property('clientkey'); - }); - }); + //TODO would need to mock this now as it is based of the modelid of the bridge + // describe('#createUser() no clientkey', () => { + // + // it('should create a user when the link button has been pressed', async () => { + // const user = await unauthenticatedHue.users.createUser('node-hue-api', 'delete-tests', true); + // expect(user).to.have.property('username').to.have.length.greaterThan(39); + // expect(user).to.not.have.property('clientkey'); + // }); + // }); describe.skip('#deleteUser()', () => { diff --git a/lib/api/http/endpoints/configuration.js b/lib/api/http/endpoints/configuration.js index b010b58..5f35716 100644 --- a/lib/api/http/endpoints/configuration.js +++ b/lib/api/http/endpoints/configuration.js @@ -53,12 +53,22 @@ function getFullState() { .pureJson(); } +function getUnAuthenticatedConfig() { + return new ApiEndpoint() + .get() + .acceptJson() + .uri('/config') + .pureJson() + .postProcess(processUnauthenticatedData); +} + module.exports = { createUser: createUser(), getConfiguration: getConfiguration(), updateConfiguration: updateConfiguration(), deleteUser: deleteUser(), - getFullState: getFullState() + getFullState: getFullState(), + getUnauthenticatedConfig: getUnAuthenticatedConfig(), }; @@ -78,6 +88,12 @@ function processCreateUser(data) { // } // } +function processUnauthenticatedData(data) { + return { + config: data + }; +} + function processDeleteUser(data) { if (util.wasSuccessful(data)) { return true; diff --git a/lib/api/stateCache.js b/lib/api/stateCache.js index 6026272..26d7b47 100644 --- a/lib/api/stateCache.js +++ b/lib/api/stateCache.js @@ -2,7 +2,6 @@ const lightBuilder = require('../bridge-model/devices/lights'); - class Cache { constructor(data) { @@ -14,7 +13,7 @@ class Cache { let light = this._lights[id]; if (!light) { - let lightData = this.data.lights[id]; + const lightData = this.data.lights[id]; if (lightData) { light = lightBuilder.create(lightData, id); this._lights[id] = light; @@ -23,5 +22,14 @@ class Cache { return light; } + + get modelid() { + // BSB001 is the first generation bridge, BSB002 is the current generation one that can support entertainment API + return this.data.config.modelid; + } + + get apiversion() { + return this.data.config.apiversion; + } } module.exports = Cache; \ No newline at end of file From fd464f4da59d72d999d44dca15e4b3bc66190eee Mon Sep 17 00:00:00 2001 From: Peter Murray <681306+peter-murray@users.noreply.github.com> Date: Tue, 19 Nov 2019 14:38:48 +0000 Subject: [PATCH 5/8] 3.4.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 087b092..a368563 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "node-hue-api", - "version": "3.4.2", + "version": "3.4.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4c04b64..d4efeb4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-hue-api", "description": "Philips Hue API Library for Node.js", - "version": "3.4.2", + "version": "3.4.3", "author": "Peter Murray ", "contributors": [ { From 8a91271b1bac9ae1a0eb2873d03ba27440a9b1d0 Mon Sep 17 00:00:00 2001 From: Peter Murray <681306+peter-murray@users.noreply.github.com> Date: Tue, 19 Nov 2019 14:40:03 +0000 Subject: [PATCH 6/8] Updating for v3.4.3 --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 26746dc..ed5e8f4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ # Change Log +## 3.4.3 +- Long term fix for supporting older bridge types and creating new users. Issue #147 + ## 3.4.2 - Temporary fix for older bridges that do not support the entertainment API. Issue #147 From 0f1f4a23eaa7e9dc22f8337bcfa071b0ecf7f9aa Mon Sep 17 00:00:00 2001 From: Peter Murray Date: Tue, 19 Nov 2019 16:32:27 +0000 Subject: [PATCH 7/8] Creating test workflow types and model --- .github/workflows/nodejs.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/nodejs.yml diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..4ea9d7e --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,26 @@ +name: Node CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [10.x, 12.x] + + steps: + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: npm test + run: | + npm ci + npm test-types --if-present + npm test-model --if-present + env: + CI: true From a05b0c69f04cc1b20643b5985270b03d5db93f0c Mon Sep 17 00:00:00 2001 From: Peter Murray Date: Tue, 19 Nov 2019 16:34:08 +0000 Subject: [PATCH 8/8] Fixing invalid test commands --- .github/workflows/nodejs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 4ea9d7e..acdb215 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -20,7 +20,7 @@ jobs: - name: npm test run: | npm ci - npm test-types --if-present - npm test-model --if-present + npm run test-types --if-present + npm run test-model --if-present env: CI: true