From 464c17d9203f90adafcb73c48e9888580cdffd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Hagelb=C3=A4ck?= Date: Thu, 1 Apr 2021 13:19:02 +0200 Subject: [PATCH] Fixes to scene handling and device unique id --- plejd/DeviceRegistry.js | 45 +++++++++++++++++++++++++++++----------- plejd/MqttClient.js | 1 - plejd/PlejdApi.js | 14 ++++++------- plejd/PlejdBLEHandler.js | 13 ++++++++---- plejd/SceneManager.js | 15 ++++++++------ 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/plejd/DeviceRegistry.js b/plejd/DeviceRegistry.js index d683ac3..6f07155 100644 --- a/plejd/DeviceRegistry.js +++ b/plejd/DeviceRegistry.js @@ -7,10 +7,12 @@ class DeviceRegistry { /** @private @type {Object.} */ devices = {}; - /** @private */ + /** @private @type {Object.} */ outputDeviceUniqueIdsByRoomId = {}; - /** @private */ + /** @private @type {Object.} */ outputUniqueIdByBleOutputAddress = {}; + /** @private @type {Object.} */ + sceneUniqueIdByBleOutputAddress = {}; /** @private @type {import('./types/ApiSite').ApiSite} */ apiSite; @@ -28,6 +30,13 @@ class DeviceRegistry { /** @param outputDevice {import('types/DeviceRegistry').OutputDevice} */ addOutputDevice(outputDevice) { + if (outputDevice.hiddenFromIntegrations || outputDevice.hiddenFromRoomList) { + logger.verbose(`Device ${outputDevice.name} is hidden and will not be included. + Hidden from room list: ${outputDevice.hiddenFromRoomList} + Hidden from integrations: ${outputDevice.hiddenFromIntegrations}`); + return; + } + this.outputDevices = { ...this.outputDevices, [outputDevice.uniqueId]: outputDevice, @@ -55,12 +64,6 @@ class DeviceRegistry { )}`, ); } - - if (outputDevice.hiddenFromIntegrations || outputDevice.hiddenFromRoomList) { - logger.verbose(`Device is hidden and should possibly not be included. - Hidden from room list: ${outputDevice.hiddenFromRoomList} - Hidden from integrations: ${outputDevice.hiddenFromIntegrations}`); - } } /** @param scene {import('types/DeviceRegistry').OutputDevice} */ @@ -85,6 +88,7 @@ class DeviceRegistry { clearSceneDevices() { this.sceneDevices = {}; + this.sceneUniqueIdByBleOutputAddress = {}; } /** @@ -135,12 +139,29 @@ class DeviceRegistry { return this.devices[deviceId]; } - getScene(sceneId) { - return this.sceneDevices[sceneId]; + /** + * @param {string} sceneUniqueId + */ + getScene(sceneUniqueId) { + return this.sceneDevices[sceneUniqueId]; } - getSceneName(sceneId) { - return (this.sceneDevices[sceneId] || {}).name; + /** + * @param {number} sceneBleAddress + */ + getSceneByBleAddress(sceneBleAddress) { + const sceneUniqueId = this.sceneUniqueIdByBleOutputAddress[sceneBleAddress]; + if (!sceneUniqueId) { + return null; + } + return this.sceneDevices[sceneUniqueId]; + } + + /** + * @param {string} sceneUniqueId + */ + getSceneName(sceneUniqueId) { + return (this.sceneDevices[sceneUniqueId] || {}).name; } // eslint-disable-next-line class-methods-use-this diff --git a/plejd/MqttClient.js b/plejd/MqttClient.js index 5ad8a1d..30b0f67 100644 --- a/plejd/MqttClient.js +++ b/plejd/MqttClient.js @@ -69,7 +69,6 @@ const getScenehDiscoveryPayload = ( ) => ({ name: sceneDevice.name, '~': getBaseTopic(sceneDevice), - state_topic: `~/${TOPICS.STATE}`, command_topic: `~/${TOPICS.COMMAND}`, optimistic: false, qos: 1, diff --git a/plejd/PlejdApi.js b/plejd/PlejdApi.js index 91d078a..2a3cc9b 100644 --- a/plejd/PlejdApi.js +++ b/plejd/PlejdApi.js @@ -325,19 +325,17 @@ class PlejdApi { `No outputSettings found for ${device.title} (${device.deviceId}), assuming output 0`, ); } - - const bleOutputAddress = this.siteDetails.outputAddress[device.deviceId][ - outputSettings ? outputSettings.output : 0 - ]; + const deviceOutput = outputSettings ? outputSettings.output : 0; + const bleOutputAddress = this.siteDetails.outputAddress[device.deviceId][deviceOutput]; if (device.traits === TRAITS.NO_LOAD) { logger.warn( `Device ${device.title} (${device.deviceId}) has no load configured and will be excluded`, ); - } else if (outputSettings) { + } else { const uniqueOutputId = this.deviceRegistry.getUniqueOutputId( device.deviceId, - outputSettings.output, + deviceOutput, ); const plejdDevice = this.siteDetails.plejdDevices.find( @@ -357,7 +355,7 @@ class PlejdApi { hiddenFromRoomList: device.hiddenFromRoomList, hiddenFromIntegrations: device.hiddenFromIntegrations, name: device.title, - output: outputSettings.output, + output: deviceOutput, roomId: device.roomId, state: undefined, type, @@ -448,7 +446,7 @@ class PlejdApi { output: undefined, roomId: undefined, state: false, - type: 'switch', + type: 'scene', typeName: 'Scene', version: undefined, uniqueId: scene.sceneId, diff --git a/plejd/PlejdBLEHandler.js b/plejd/PlejdBLEHandler.js index 1ea20ad..638c94e 100644 --- a/plejd/PlejdBLEHandler.js +++ b/plejd/PlejdBLEHandler.js @@ -846,13 +846,18 @@ class PlejBLEHandler extends EventEmitter { command = state ? COMMANDS.TURN_ON : COMMANDS.TURN_OFF; this.emit(PlejBLEHandler.EVENTS.commandReceived, outputUniqueId, command, data); } else if (cmd === BLE_CMD_SCENE_TRIG) { - const sceneId = state; - const sceneName = this.deviceRegistry.getSceneName(sceneId); + const sceneBleAddress = state; + const scene = this.deviceRegistry.getSceneByBleAddress(sceneBleAddress); - logger.debug(`${sceneName} (${sceneId}) scene triggered (device id ${outputUniqueId}).`); + if (!scene) { + logger.warn(`Scene with BLE address ${sceneBleAddress} could not be found, can't process message`); + return; + } + + logger.debug(`${scene.name} (${sceneBleAddress}) scene triggered (device id ${outputUniqueId}).`); command = COMMANDS.TRIGGER_SCENE; - data = { sceneId }; + data = { sceneId: scene.uniqueId }; this.emit(PlejBLEHandler.EVENTS.commandReceived, outputUniqueId, command, data); } else if (cmd === BLE_CMD_TIME_UPDATE) { const now = new Date(); diff --git a/plejd/SceneManager.js b/plejd/SceneManager.js index 4f518ad..54dc256 100644 --- a/plejd/SceneManager.js +++ b/plejd/SceneManager.js @@ -7,7 +7,7 @@ class SceneManager { deviceRegistry; /** @private @type {import('./PlejdDeviceCommunication')} */ plejdDeviceCommunication; - /** @private @type {Object.} */ + /** @private @type {Object.} */ scenes; constructor(deviceRegistry, plejdDeviceCommunication) { @@ -23,15 +23,18 @@ class SceneManager { this.scenes = {}; scenes.forEach((scene) => { - const idx = this.deviceRegistry.getApiSite().sceneIndex[scene.sceneId]; - this.scenes[idx] = new Scene(this.deviceRegistry, idx, scene); + const sceneBleAddress = this.deviceRegistry.getApiSite().sceneIndex[scene.sceneId]; + this.scenes[scene.sceneId] = new Scene(this.deviceRegistry, sceneBleAddress, scene); }); } - executeScene(sceneId) { - const scene = this.scenes[sceneId]; + /** + * @param {string} sceneUniqueId + */ + executeScene(sceneUniqueId) { + const scene = this.scenes[sceneUniqueId]; if (!scene) { - logger.info(`Scene with id ${sceneId} not found`); + logger.info(`Scene with id ${sceneUniqueId} not found`); logger.verbose(`Scenes: ${JSON.stringify(this.scenes, null, 2)}`); return; }