diff --git a/front/src/config/i18n/en.json b/front/src/config/i18n/en.json
index e266644131..61c921a518 100644
--- a/front/src/config/i18n/en.json
+++ b/front/src/config/i18n/en.json
@@ -452,8 +452,13 @@
"connectButton": "Connect/Reconnect",
"scanButton": "Scan network",
"bridgeButtonNotPressed": "Bridge button not pressed: Please press the button on your Philips Hue bridge and try again.",
- "unknownError": "An unknown error occured. Please try again or contact Gladys community.",
- "noBridgesFound": "We didn't find any Philips Hue bridges on your network. Are you sure you are connected to the same network as your bridge and your bridge is turned on?"
+ "unknownError": "An unknown error occurred. Please try again or contact Gladys community.",
+ "noBridgesFound": "We didn't find any Philips Hue bridges on your network. Are you sure you are connected to the same network as your bridge and your bridge is turned on?",
+ "manualConfiguration": {
+ "title": "Manual configuration",
+ "text": "If you know the IP address of your Philips Hue bridge, you can fill it and launch a manual connection.",
+ "input": "IP address"
+ }
},
"device": {
"title": "Devices in Gladys",
diff --git a/front/src/config/i18n/fr.json b/front/src/config/i18n/fr.json
index 44626f502e..5d7a9b76a8 100644
--- a/front/src/config/i18n/fr.json
+++ b/front/src/config/i18n/fr.json
@@ -579,7 +579,12 @@
"scanButton": "Recherche sur le réseau",
"bridgeButtonNotPressed": "Le bouton du pont n'a pas été appuyé : veuillez appuyer sur le bouton de votre pont Philips Hue et réessayer.",
"unknownError": "Une erreur inconnue s'est produite. Veuillez réessayer ou contacter Gladys community .",
- "noBridgesFound": "Nous n'avons trouvé aucun pont Philips Hue sur votre réseau. Êtes-vous sûr que vous êtes connecté au même réseau que votre pont et que celui-ci est sous tension?"
+ "noBridgesFound": "Nous n'avons trouvé aucun pont Philips Hue sur votre réseau. Êtes-vous sûr que vous êtes connecté au même réseau que votre pont et que celui-ci est sous tension?",
+ "manualConfiguration": {
+ "title": "Configuration manuelle",
+ "text": "Si vous connaissez l'adresse IP de votre pont Philips Hue, vous pouvez la saisir et lancer une configuration manuelle.",
+ "input": "Adresse IP"
+ }
},
"device": {
"title": "Appareils dans Gladys",
diff --git a/front/src/routes/integration/all/philips-hue/setup-page/SetupTab.jsx b/front/src/routes/integration/all/philips-hue/setup-page/SetupTab.jsx
index b7255f1e65..b7b62edc49 100644
--- a/front/src/routes/integration/all/philips-hue/setup-page/SetupTab.jsx
+++ b/front/src/routes/integration/all/philips-hue/setup-page/SetupTab.jsx
@@ -1,126 +1,166 @@
-import { MarkupText, Text } from 'preact-i18n';
+import { Component } from 'preact';
+import { MarkupText, Text, Localizer } from 'preact-i18n';
import cx from 'classnames';
import { RequestStatus } from '../../../../../utils/consts';
import style from './style.css';
-const disconnectBridge = (props, device, index) => () => {
- props.deleteDevice(device, index);
-};
+class SetupTab extends Component {
+ disconnectBridge = (props, device, index) => () => {
+ props.deleteDevice(device, index);
+ };
-const connectBridge = (props, device) => () => {
- props.connectBridge(device);
-};
+ connectBridge = (props, device) => () => {
+ props.connectBridge(device);
+ };
-const SetupTab = ({ children, ...props }) => {
- return (
-
- {props.philipsHueBridgesDevices && props.philipsHueBridgesDevices.length > 0 && (
+ setmanualBridgeConfiguration = ipaddress => {
+ this.setState({ manualBridgeConfiguration: { ipaddress: ipaddress.target.value } });
+ };
+
+ render(props) {
+ return (
+
+ {props.philipsHueBridgesDevices && props.philipsHueBridgesDevices.length > 0 && (
+
+
+
+
+
+
+ {props.philipsHueDeleteDeviceStatus === RequestStatus.Error && (
+
+
+
+ )}
+ {props.philipsHueGetDevicesStatus === RequestStatus.Getting &&
}
+
+ {props.philipsHueBridgesDevices &&
+ props.philipsHueBridgesDevices.map((bridge, index) => (
+
+ ))}
+
+
+
+
+
+ )}
- {props.philipsHueDeleteDeviceStatus === RequestStatus.Error && (
-
-
-
- )}
- {props.philipsHueGetDevicesStatus === RequestStatus.Getting &&
}
-
- {props.philipsHueBridgesDevices &&
- props.philipsHueBridgesDevices.map((bridge, index) => (
-
-
-
-
- )}
-
-
-
-
-
-
- {props.philipsHueGetBridgesStatus === RequestStatus.Getting &&
}
- {props.philipsHueBridges && props.philipsHueBridges.length === 0 && (
-
-
- )}
- {props.philipsHueCreateDeviceStatus === RequestStatus.PhilipsHueBridgeButtonNotPressed && (
-
-
-
- )}
- {props.philipsHueCreateDeviceStatus === RequestStatus.Error && (
-
-
-
- )}
- {props.philipsHueBridges &&
- props.philipsHueBridges.map(bridge => (
-
-
-
-
-
-
-
+ )}
+ {props.philipsHueCreateDeviceStatus === RequestStatus.PhilipsHueBridgeButtonNotPressed && (
+
+
+
+ )}
+ {props.philipsHueCreateDeviceStatus === RequestStatus.Error && (
+
+
+
+ )}
+ {props.philipsHueBridges &&
+ props.philipsHueBridges.map(bridge => (
+
-
- ))}
+ ))}
+
-
- );
-};
+ );
+ }
+}
export default SetupTab;
diff --git a/front/src/routes/integration/all/philips-hue/setup-page/actions.js b/front/src/routes/integration/all/philips-hue/setup-page/actions.js
index ed47c136c0..a0a9fc8bc7 100644
--- a/front/src/routes/integration/all/philips-hue/setup-page/actions.js
+++ b/front/src/routes/integration/all/philips-hue/setup-page/actions.js
@@ -66,7 +66,7 @@ const actions = store => ({
});
try {
const createdDevice = await state.httpClient.post('/api/v1/service/philips-hue/bridge/configure', {
- serial: bridge.model.serial
+ ipAddress: bridge.ipaddress
});
const newState = update(state, {
philipsHueBridgesDevices: {
diff --git a/server/services/philips-hue/api/hue.controller.js b/server/services/philips-hue/api/hue.controller.js
index 35feb0ff7f..76d1fa5878 100644
--- a/server/services/philips-hue/api/hue.controller.js
+++ b/server/services/philips-hue/api/hue.controller.js
@@ -14,11 +14,11 @@ module.exports = function HueController(philipsHueLightHandler) {
/**
* @api {post} /api/v1/service/philips-hue/bridge/configure Configure Philips Hue Bridge
* @apiName ConfigureBridge
- * @apiParam {String} serial Serial number of the bridge
+ * @apiParam {String} ipAddress IP Address of the bridge
* @apiGroup PhilipsHue
*/
async function configureBridge(req, res) {
- const bridge = await philipsHueLightHandler.configureBridge(req.body.serial);
+ const bridge = await philipsHueLightHandler.configureBridge(req.body.ipAddress);
res.json(bridge);
}
diff --git a/server/services/philips-hue/lib/light/index.js b/server/services/philips-hue/lib/light/index.js
index c9cedb1614..5e2eb702cf 100644
--- a/server/services/philips-hue/lib/light/index.js
+++ b/server/services/philips-hue/lib/light/index.js
@@ -35,7 +35,7 @@ const PhilipsHueLightHandler = function PhilipsHueLightHandler(gladys, hueClient
this.serviceId = serviceId;
this.bridges = [];
this.connnectedBridges = [];
- this.bridgesBySerialNumber = new Map();
+ this.bridgesByIP = new Map();
this.hueApisBySerialNumber = new Map();
this.lights = [];
};
diff --git a/server/services/philips-hue/lib/light/light.configureBridge.js b/server/services/philips-hue/lib/light/light.configureBridge.js
index c3566050bd..7b48d155c5 100644
--- a/server/services/philips-hue/lib/light/light.configureBridge.js
+++ b/server/services/philips-hue/lib/light/light.configureBridge.js
@@ -1,5 +1,4 @@
const logger = require('../../../../utils/logger');
-const { NotFoundError } = require('../../../../utils/coreErrors');
const { Error403 } = require('../../../../utils/httpErrors');
const {
HUE_DEVICE_NAME,
@@ -13,34 +12,39 @@ const {
/**
* @description Configure the philips hue bridge.
- * @param {string} serialNumber - Serial number of the Philips Hue Bridge.
+ * @param {string} ipAddress - IP Address of the Philips Hue Bridge.
* @returns {Promise
} Resolve with created device.
* @example
* configureBridge('162.198.1.1');
*/
-async function configureBridge(serialNumber) {
- const bridge = this.bridgesBySerialNumber.get(serialNumber);
+async function configureBridge(ipAddress) {
+ const bridge = this.bridgesByIP.get(ipAddress);
if (!bridge) {
- throw new NotFoundError(`BRIDGE_NOT_FOUND`);
+ logger.info(`Connecting to hue bridge ip = ${ipAddress} manually (not from discovered bridges)...`);
+ } else {
+ logger.info(`Connecting to hue bridge "${bridge.name}", ip = ${ipAddress} (from discovered bridges)...`);
}
- logger.info(`Connecting to hue bridge "${serialNumber}", ip = ${bridge.ipaddress}...`);
try {
const hueApi = this.hueClient.api;
- const unauthenticatedApi = await hueApi.createLocal(bridge.ipaddress).connect();
+ const unauthenticatedApi = await hueApi.createLocal(ipAddress).connect();
const user = await unauthenticatedApi.users.createUser(HUE_APP_NAME, HUE_DEVICE_NAME);
- const authenticatedApi = await hueApi.createLocal(bridge.ipaddress).connect(user.username);
- this.hueApisBySerialNumber.set(serialNumber, authenticatedApi);
+ const authenticatedApi = await hueApi.createLocal(ipAddress).connect(user.username);
+ // Get configuration to fetch serialNumber
+ const bridgeConfig = await authenticatedApi.configuration.get();
+ const bridgeSerialNumber = bridgeConfig.bridgeid;
+ const bridgeName = bridge ? bridge.name : bridgeConfig.name;
+ this.hueApisBySerialNumber.set(bridgeSerialNumber, authenticatedApi);
const deviceCreated = await this.gladys.device.create({
- name: bridge.name,
+ name: bridgeName,
service_id: this.serviceId,
- external_id: `${BRIDGE_EXTERNAL_ID_BASE}:${serialNumber}`,
- selector: `${BRIDGE_EXTERNAL_ID_BASE}:${serialNumber}`,
+ external_id: `${BRIDGE_EXTERNAL_ID_BASE}:${bridgeSerialNumber}`,
+ selector: `${BRIDGE_EXTERNAL_ID_BASE}:${bridgeSerialNumber}`,
model: BRIDGE_MODEL,
features: [],
params: [
{
name: BRIDGE_IP_ADDRESS,
- value: bridge.ipaddress,
+ value: ipAddress,
},
{
name: BRIDGE_USERNAME,
@@ -48,7 +52,7 @@ async function configureBridge(serialNumber) {
},
{
name: BRIDGE_SERIAL_NUMBER,
- value: serialNumber,
+ value: bridgeSerialNumber,
},
],
});
diff --git a/server/services/philips-hue/lib/light/light.getBridges.js b/server/services/philips-hue/lib/light/light.getBridges.js
index 8f1e891f67..9ef12b73af 100644
--- a/server/services/philips-hue/lib/light/light.getBridges.js
+++ b/server/services/philips-hue/lib/light/light.getBridges.js
@@ -9,10 +9,18 @@ const TIMEOUT = 10000;
* getBridges();
*/
async function getBridges() {
- this.bridges = await this.hueClient.discovery.upnpSearch(TIMEOUT);
- logger.info(`PhilipsHueService: Found ${this.bridges.length} bridges`);
+ // Launch faster N-UPnP Search
+ this.bridges = await this.hueClient.discovery.nupnpSearch();
+ logger.info(`PhilipsHueService: Found ${this.bridges.length} bridges with N-UPnP Search`);
+
+ // Fallback on UPnP Search
+ if (this.bridges.length === 0) {
+ this.bridges = await this.hueClient.discovery.upnpSearch(TIMEOUT);
+ logger.info(`PhilipsHueService: Found ${this.bridges.length} bridges with UPnP Search`);
+ }
+
this.bridges.forEach((bridge) => {
- this.bridgesBySerialNumber.set(bridge.model.serial, bridge);
+ this.bridgesByIP.set(bridge.ipaddress, bridge);
});
return this.bridges;
}
diff --git a/server/services/philips-hue/package-lock.json b/server/services/philips-hue/package-lock.json
index 87439c104d..750d60335f 100644
--- a/server/services/philips-hue/package-lock.json
+++ b/server/services/philips-hue/package-lock.json
@@ -20,15 +20,15 @@
"dependencies": {
"bluebird": "^3.7.0",
"bottleneck": "^2.19.5",
- "node-hue-api": "^4.0.9"
+ "node-hue-api": "^4.0.11"
}
},
"node_modules/axios": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
- "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+ "version": "0.21.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+ "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
- "follow-redirects": "^1.10.0"
+ "follow-redirects": "^1.14.0"
}
},
"node_modules/bluebird": {
@@ -42,9 +42,9 @@
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
},
"node_modules/follow-redirects": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
- "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==",
+ "version": "1.15.3",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
+ "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
"funding": [
{
"type": "individual",
@@ -66,9 +66,9 @@
"integrity": "sha512-aKYXS1S5+2IYw4W5+lKC/M+lvaNYPe0PhnQ144NWARcBg35H3ZvyVZ6y0LNGtiAxggFBHeO7LaVGO4bgHK4g1Q=="
},
"node_modules/node-hue-api": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/node-hue-api/-/node-hue-api-4.0.10.tgz",
- "integrity": "sha512-s+UvFttQfNXFadk8p6N9q9A5hteY2Q48W/mVze9nFPR5gwPH374cdA61ezKOx1WgBrN4btHj1z81veznhEZZAA==",
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/node-hue-api/-/node-hue-api-4.0.11.tgz",
+ "integrity": "sha512-lpnDdMjLTmm00JRsU70Mtm0Ix03cf7PRjKQAJbSg/Y0ChiIKQs+oDbSUpW2aDhEbor+wKpyfLYLGLTrjlG24pQ==",
"dependencies": {
"axios": "^0.21.1",
"bottleneck": "^2.19.5",
@@ -81,11 +81,11 @@
},
"dependencies": {
"axios": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
- "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+ "version": "0.21.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+ "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
- "follow-redirects": "^1.10.0"
+ "follow-redirects": "^1.14.0"
}
},
"bluebird": {
@@ -99,9 +99,9 @@
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
},
"follow-redirects": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
- "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA=="
+ "version": "1.15.3",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
+ "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q=="
},
"get-ssl-certificate": {
"version": "2.3.3",
@@ -109,9 +109,9 @@
"integrity": "sha512-aKYXS1S5+2IYw4W5+lKC/M+lvaNYPe0PhnQ144NWARcBg35H3ZvyVZ6y0LNGtiAxggFBHeO7LaVGO4bgHK4g1Q=="
},
"node-hue-api": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/node-hue-api/-/node-hue-api-4.0.10.tgz",
- "integrity": "sha512-s+UvFttQfNXFadk8p6N9q9A5hteY2Q48W/mVze9nFPR5gwPH374cdA61ezKOx1WgBrN4btHj1z81veznhEZZAA==",
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/node-hue-api/-/node-hue-api-4.0.11.tgz",
+ "integrity": "sha512-lpnDdMjLTmm00JRsU70Mtm0Ix03cf7PRjKQAJbSg/Y0ChiIKQs+oDbSUpW2aDhEbor+wKpyfLYLGLTrjlG24pQ==",
"requires": {
"axios": "^0.21.1",
"bottleneck": "^2.19.5",
diff --git a/server/services/philips-hue/package.json b/server/services/philips-hue/package.json
index f0c308350a..efbad9698c 100644
--- a/server/services/philips-hue/package.json
+++ b/server/services/philips-hue/package.json
@@ -15,6 +15,6 @@
"dependencies": {
"bluebird": "^3.7.0",
"bottleneck": "^2.19.5",
- "node-hue-api": "^4.0.9"
+ "node-hue-api": "^4.0.11"
}
}
diff --git a/server/test/services/philips-hue/controllers/configureBridge.controller.test.js b/server/test/services/philips-hue/controllers/configureBridge.controller.test.js
index b24c36c6eb..91a90030b7 100644
--- a/server/test/services/philips-hue/controllers/configureBridge.controller.test.js
+++ b/server/test/services/philips-hue/controllers/configureBridge.controller.test.js
@@ -14,10 +14,10 @@ describe('POST /service/philips-hue/bridge/configure', () => {
const philipsHueController = PhilipsHueControllers(philipsHueLightService);
const req = {
body: {
- serial: '12345',
+ ipAddress: '192.168.1.10',
},
};
await philipsHueController['post /api/v1/service/philips-hue/bridge/configure'].controller(req, res);
- assert.calledWith(philipsHueLightService.configureBridge, '12345');
+ assert.calledWith(philipsHueLightService.configureBridge, '192.168.1.10');
});
});
diff --git a/server/test/services/philips-hue/light/light.configureBridge.test.js b/server/test/services/philips-hue/light/light.configureBridge.test.js
index 7ae5210a49..7a86640f51 100644
--- a/server/test/services/philips-hue/light/light.configureBridge.test.js
+++ b/server/test/services/philips-hue/light/light.configureBridge.test.js
@@ -26,14 +26,14 @@ describe('PhilipsHueService', () => {
it('should configure bridge', async () => {
const philipsHueService = PhilipsHueService(gladys, 'a810b8db-6d04-4697-bed3-c4b72c996279');
await philipsHueService.device.getBridges();
- const device = await philipsHueService.device.configureBridge('1234');
+ const device = await philipsHueService.device.configureBridge('192.168.1.10');
expect(device).to.have.property('name', 'Philips Hue Bridge');
expect(device).to.have.property('selector', 'philips-hue-bridge-1234');
expect(device).to.have.property('external_id', 'philips-hue:bridge:1234');
expect(device).to.have.property('features');
expect(device).to.have.property('params');
expect(device.params[0]).to.have.property('name', 'BRIDGE_IP_ADDRESS');
- expect(device.params[0]).to.have.property('value', '192.168.2.245');
+ expect(device.params[0]).to.have.property('value', '192.168.1.10');
expect(device.params[1]).to.have.property('name', 'BRIDGE_USERNAME');
expect(device.params[1]).to.have.property('value', 'username');
expect(device.params[2]).to.have.property('name', 'BRIDGE_SERIAL_NUMBER');
diff --git a/server/test/services/philips-hue/light/light.getBridges.test.js b/server/test/services/philips-hue/light/light.getBridges.test.js
index 9a340c6a0e..18f9ea6a20 100644
--- a/server/test/services/philips-hue/light/light.getBridges.test.js
+++ b/server/test/services/philips-hue/light/light.getBridges.test.js
@@ -1,15 +1,29 @@
const { expect } = require('chai');
const proxyquire = require('proxyquire').noCallThru();
-const { MockedPhilipsHueClient } = require('../mocks.test');
+const { MockedPhilipsHueClient, MockedPhilipsHueClientUpnp } = require('../mocks.test');
const PhilipsHueService = proxyquire('../../../../services/philips-hue/index', {
'node-hue-api': MockedPhilipsHueClient,
});
+const PhilipsHueServiceUpnp = proxyquire('../../../../services/philips-hue/index', {
+ 'node-hue-api': MockedPhilipsHueClientUpnp,
+});
+
describe('PhilipsHueService', () => {
- it('getBridges should return bridges', async () => {
+ it('getBridges should return bridges with nupnp Search', async () => {
const philipsHueService = PhilipsHueService();
const bridges = await philipsHueService.device.getBridges();
+ expect(bridges).to.deep.equal([
+ {
+ name: 'Philips Hue Bridge',
+ ipaddress: '192.168.1.10',
+ },
+ ]);
+ });
+ it('getBridges should return bridges with upnp Search', async () => {
+ const philipsHueService = PhilipsHueServiceUpnp();
+ const bridges = await philipsHueService.device.getBridges();
expect(bridges).to.deep.equal([
{
name: 'Philips Hue Bridge',
diff --git a/server/test/services/philips-hue/mocks.test.js b/server/test/services/philips-hue/mocks.test.js
index da7984ba8b..a58800ac84 100644
--- a/server/test/services/philips-hue/mocks.test.js
+++ b/server/test/services/philips-hue/mocks.test.js
@@ -59,6 +59,12 @@ const hueApi = {
]),
activateScene: fake.resolves(null),
},
+ configuration: {
+ get: () =>
+ Promise.resolve({
+ bridgeid: '1234',
+ }),
+ },
};
const MockedPhilipsHueClient = {
@@ -72,6 +78,29 @@ const MockedPhilipsHueClient = {
}),
},
discovery: {
+ nupnpSearch: () =>
+ Promise.resolve([
+ {
+ name: 'Philips Hue Bridge',
+ ipaddress: '192.168.1.10',
+ },
+ ]),
+ },
+ },
+};
+
+const MockedPhilipsHueClientUpnp = {
+ v3: {
+ lightStates: {
+ LightState,
+ },
+ api: {
+ createLocal: () => ({
+ connect: () => hueApi,
+ }),
+ },
+ discovery: {
+ nupnpSearch: () => Promise.resolve([]),
upnpSearch: () =>
Promise.resolve([
{
@@ -88,6 +117,7 @@ const MockedPhilipsHueClient = {
module.exports = {
MockedPhilipsHueClient,
+ MockedPhilipsHueClientUpnp,
STATE_ON,
STATE_OFF,
fakes,