From 4608de5d5799be424140f6b2233f06e0f5209734 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Mon, 11 Oct 2021 17:30:35 +0200 Subject: [PATCH] Allow publishing to device by endpoint ID. https://github.com/nurikk/zigbee2mqtt-frontend/issues/926 --- lib/extension/publish.ts | 10 ++++++++-- test/publish.test.js | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/extension/publish.ts b/lib/extension/publish.ts index 44f047c42..df6759ddd 100644 --- a/lib/extension/publish.ts +++ b/lib/extension/publish.ts @@ -9,8 +9,8 @@ import Group from '../model/group'; import Device from '../model/device'; import bind from 'bind-decorator'; -const topicRegex = new RegExp(`^(.+?)(?:/(${utils.endpointNames.join('|')}))?/(get|set)(?:/(.+))?`); -const propertyEndpointRegex = new RegExp(`^(.*)_(${utils.endpointNames.join('|')})$`); +const topicRegex = new RegExp(`^(.+?)(?:/(${utils.endpointNames.join('|')}|\\d+))?/(get|set)(?:/(.+))?`); +const propertyEndpointRegex = new RegExp(`^(.*)_(${utils.endpointNames.join('|')}|\\d+)$`); const stateValues = ['on', 'off', 'toggle', 'open', 'close', 'stop', 'lock', 'unlock']; const sceneConverterKeys = ['scene_store', 'scene_add', 'scene_remove', 'scene_remove_all']; @@ -220,6 +220,12 @@ export default class Publish extends Extension { continue; } + // If the endpoint_name name is a nubmer, try to map it to a friendlyName + if (!isNaN(Number(endpointName)) && re.isDevice() && utils.isEndpoint(localTarget) && + re.endpointName(localTarget)) { + endpointName = re.endpointName(localTarget); + } + // Converter didn't return a result, skip const meta = {endpoint_name: endpointName, options: entitySettings, message: {...message}, logger, device, state: entityState, membersState, mapped: definition}; diff --git a/test/publish.test.js b/test/publish.test.js index c276c5f55..ef94c06a0 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -186,6 +186,17 @@ describe('Publish', () => { expect(MQTT.publish.mock.calls[1][2]).toStrictEqual({"qos": 0, "retain": false}); }); + it('Should publish messages to zigbee devices with endpoint ID', async () => { + const device = zigbeeHerdsman.devices.QBKG03LM; + const endpoint = device.getEndpoint(3); + await MQTT.events.message('zigbee2mqtt/wall_switch_double/3/set', stringify({state: 'OFF'})); + await flushPromises(); + expect(endpoint.command).toHaveBeenCalledTimes(1); + expect(endpoint.command).toHaveBeenCalledWith("genOnOff", "off", {}, {}); + expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/wall_switch_double', stringify({state_right: 'OFF'}), + {"qos": 0, "retain": false}, expect.any(Function)); + }); + 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);