From fdc8fcc02b8ff58db13dbbd42397502d92e96897 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Wed, 20 Nov 2019 17:36:36 +0100 Subject: [PATCH] Allow to specify endpoint via property. #2356 --- lib/extension/entityPublish.js | 29 ++++++++++++++++++++++------- test/entityPublish.test.js | 13 +++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/lib/extension/entityPublish.js b/lib/extension/entityPublish.js index 667e680e..8d895e95 100644 --- a/lib/extension/entityPublish.js +++ b/lib/extension/entityPublish.js @@ -124,7 +124,22 @@ class EntityPublish extends BaseExtension { // For each attribute call the corresponding converter const usedConverters = []; - for (const [key, value] of entries) { + for (let [key, value] of entries) { + let postfix = topic.postfix; + let actualTarget = target; + + // When the key has a postfix included (e.g. state_right), this will override the target. + if (entity.type === 'device' && key.includes('_')) { + const underscoreIndex = key.lastIndexOf('_'); + const possiblePostfix = key.substring(underscoreIndex + 1, key.length); + if (utils.getPostfixes().includes(possiblePostfix)) { + postfix = possiblePostfix; + key = key.substring(0, underscoreIndex); + const device = target.getDevice(); + actualTarget = device.getEndpoint(mapped.endpoint(device)[postfix]); + } + } + const converter = converters.find((c) => c.key.includes(key)); if (usedConverters.includes(converter)) { @@ -139,7 +154,7 @@ class EntityPublish extends BaseExtension { // Converter didn't return a result, skip const meta = { - endpoint_name: topic.postfix, + endpoint_name: postfix, options, message: json, logger, @@ -151,12 +166,12 @@ class EntityPublish extends BaseExtension { try { if (topic.type === 'set' && converter && converter.convertSet) { logger.debug(`Publishing '${topic.type}' '${key}' to '${entity.name}'`); - const result = await converter.convertSet(target, key, value, meta); + const result = await converter.convertSet(actualTarget, key, value, meta); if (result && result.hasOwnProperty('state')) { const msg = result.state; - if (topic.postfix) { - msg[`state_${topic.postfix}`] = msg.state; + if (postfix) { + msg[`state_${postfix}`] = msg.state; delete msg.state; } @@ -174,11 +189,11 @@ class EntityPublish extends BaseExtension { entity.type === 'device' && result && result.hasOwnProperty('readAfterWriteTime') && entity.settings.retrieve_state ) { - setTimeout(() => converter.convertGet(target, key, meta), result.readAfterWriteTime); + setTimeout(() => converter.convertGet(actualTarget, key, meta), result.readAfterWriteTime); } } else if (topic.type === 'get' && converter && converter.convertGet) { logger.debug(`Publishing get '${topic.type}' '${key}' to '${entity.name}'`); - await converter.convertGet(target, key, meta); + await converter.convertGet(actualTarget, key, meta); } else { logger.error(`No converter available for '${topic.type}' '${key}' (${json[key]})`); continue; diff --git a/test/entityPublish.test.js b/test/entityPublish.test.js index 12d6c8ea..8cb98d5a 100644 --- a/test/entityPublish.test.js +++ b/test/entityPublish.test.js @@ -168,6 +168,19 @@ describe('Entity publish', () => { expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false}); }); + it('Should publish messages to zigbee devices to non default-ep with state_[EP]', async () => { + const device = zigbeeHerdsman.devices.QBKG03LM; + const endpoint = device.getEndpoint(3); + await MQTT.events.message('zigbee2mqtt/wall_switch_double/set', JSON.stringify({state_right: 'OFF'})); + await flushPromises(); + expect(endpoint.command).toHaveBeenCalledTimes(1); + expect(endpoint.command).toHaveBeenCalledWith("genOnOff", "off", {}, {}); + expect(MQTT.publish).toHaveBeenCalledTimes(1); + expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/wall_switch_double'); + expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({state_right: 'OFF'}); + expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false}); + }); + it('Should publish messages to zigbee devices with color xy', async () => { const device = zigbeeHerdsman.devices.bulb_color; const endpoint = device.getEndpoint(1);