diff --git a/lib/controller.js b/lib/controller.js index f407d8c8..d6a2fb9a 100644 --- a/lib/controller.js +++ b/lib/controller.js @@ -8,7 +8,7 @@ const objectAssignDeep = require('object-assign-deep'); const utils = require('./util/utils'); // Extensions -const ExtensionEntityPublish = require('./extension/entityPublish'); +const ExtensionPublish = require('./extension/publish'); const ExtensionReceive = require('./extension/receive'); const ExtensionNetworkMap = require('./extension/networkMap'); const ExtensionSoftReset = require('./extension/legacy/softReset'); @@ -36,7 +36,7 @@ class Controller { // Initialize extensions. const args = [this.zigbee, this.mqtt, this.state, this.publishEntityState, this.eventBus]; this.extensions = [ - new ExtensionEntityPublish(...args), + new ExtensionPublish(...args), new ExtensionReceive(...args), new ExtensionDeviceGroupMembership(...args), new ExtensionConfigure(...args), diff --git a/lib/extension/entityPublish.js b/lib/extension/publish.js similarity index 75% rename from lib/extension/entityPublish.js rename to lib/extension/publish.js index 9205376c..69d49d4f 100644 --- a/lib/extension/entityPublish.js +++ b/lib/extension/publish.js @@ -6,8 +6,7 @@ const utils = require('../util/utils'); const assert = require('assert'); const Extension = require('./extension'); -const postfixes = utils.getEndpointNames(); -const topicRegex = new RegExp(`^(.+?)(?:/(${postfixes.join('|')}))?/(get|set)(?:/(.+))?`); +const topicRegex = new RegExp(`^(.+?)(?:/(${utils.getEndpointNames().join('|')}))?/(get|set)(?:/(.+))?`); const groupConverters = [ zigbeeHerdsmanConverters.toZigbeeConverters.light_onoff_brightness, @@ -46,7 +45,7 @@ class EntityPublish extends Extension { return null; } - return {ID: ID, postfix: match[2] || '', type: match[3], attribute: match[4]}; + return {ID: ID, endpointName: match[2] || '', type: match[3], attribute: match[4]}; } async onMQTTMessage(topic, message) { @@ -55,20 +54,20 @@ class EntityPublish extends Extension { return false; } - const entityName = `${topic.ID}` + (topic.postfix ? `/${topic.postfix}` : ''); - const entity = this.zigbee.resolveEntity(entityName); + const entityKey = `${topic.ID}` + (topic.endpointName ? `/${topic.endpointName}` : ''); + const resolvedEntity = this.zigbee.resolveEntity(entityKey); - if (!entity) { + if (!resolvedEntity) { /* istanbul ignore else */ if (settings.get().advanced.legacy_api) { - const message = {friendly_name: entityName}; + const message = {friendly_name: entityKey}; this.mqtt.publish( 'bridge/log', JSON.stringify({type: `entity_not_found`, message}), ); } - logger.error(`Entity '${entityName}' is unknown`); + logger.error(`Entity '${entityKey}' is unknown`); return; } @@ -77,27 +76,26 @@ class EntityPublish extends Extension { let target = null; let options = {}; let device = null; - let mapped = null; + let definition = null; - assert(entity.type === 'device' || entity.type === 'group'); - if (entity.type === 'device') { - // Map device to a model - if (!entity.definition) { - logger.warn(`Device with modelID '${entity.device.modelID}' is not supported.`); + assert(resolvedEntity.type === 'device' || resolvedEntity.type === 'group'); + if (resolvedEntity.type === 'device') { + if (!resolvedEntity.definition) { + logger.warn(`Device with modelID '${resolvedEntity.device.modelID}' is not supported.`); logger.warn(`Please see: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html`); return; } - device = entity.device; - mapped = entity.definition; - target = entity.endpoint; - converters = entity.definition.toZigbee; - options = entity.settings; + device = resolvedEntity.device; + definition = resolvedEntity.definition; + target = resolvedEntity.endpoint; + converters = resolvedEntity.definition.toZigbee; + options = resolvedEntity.settings; } else { converters = groupConverters; - target = entity.group; - options = entity.settings; - mapped = entity.group.members.map((e) => zigbeeHerdsmanConverters.findByDevice(e.getDevice())); + target = resolvedEntity.group; + options = resolvedEntity.settings; + definition = resolvedEntity.group.members.map((e) => zigbeeHerdsmanConverters.findByDevice(e.getDevice())); } // Convert the MQTT message to a Zigbee message. @@ -113,7 +111,7 @@ class EntityPublish extends Extension { } } - const deviceState = this.state.get(entity.settings.ID) || {}; + const deviceState = this.state.get(resolvedEntity.settings.ID) || {}; const isOn = deviceState && deviceState.state === 'ON' ? true : false; /** @@ -148,18 +146,18 @@ class EntityPublish extends Extension { // For each attribute call the corresponding converter const usedConverters = []; for (let [key, value] of entries) { - let postfix = topic.postfix; + let endpointName = topic.endpointName; 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('_')) { + // When the key has a endpointName included (e.g. state_right), this will override the target. + if (resolvedEntity.type === 'device' && key.includes('_')) { const underscoreIndex = key.lastIndexOf('_'); - const possiblePostfix = key.substring(underscoreIndex + 1, key.length); - if (utils.getEndpointNames().includes(possiblePostfix)) { - postfix = possiblePostfix; + const possibleEndpointName = key.substring(underscoreIndex + 1, key.length); + if (utils.getEndpointNames().includes(possibleEndpointName)) { + endpointName = possibleEndpointName; key = key.substring(0, underscoreIndex); const device = target.getDevice(); - actualTarget = device.getEndpoint(mapped.endpoint(device)[postfix]); + actualTarget = device.getEndpoint(definition.endpoint(device)[endpointName]); } } @@ -177,32 +175,32 @@ class EntityPublish extends Extension { // Converter didn't return a result, skip const meta = { - endpoint_name: postfix, + endpoint_name: endpointName, options, message: json, logger, device, state: deviceState, - mapped, + mapped: definition, }; try { if (topic.type === 'set' && converter.convertSet) { - logger.debug(`Publishing '${topic.type}' '${key}' to '${entity.name}'`); + logger.debug(`Publishing '${topic.type}' '${key}' to '${resolvedEntity.name}'`); const result = await converter.convertSet(actualTarget, key, value, meta); if (result && result.state) { const msg = result.state; - if (postfix) { + if (endpointName) { for (const key of ['state', 'brightness']) { if (msg.hasOwnProperty(key)) { - msg[`${key}_${postfix}`] = msg[key]; + msg[`${key}_${endpointName}`] = msg[key]; delete msg[key]; } } } - this.publishEntityState(entity.settings.ID, msg); + this.publishEntityState(resolvedEntity.settings.ID, msg); } // It's possible for devices to get out of sync when writing an attribute that's not reportable. @@ -213,13 +211,13 @@ class EntityPublish extends Extension { // ever issue a read here, as we assume the device will properly report changes. // Only do this when the retrieve_state option is enabled for this device. if ( - entity.type === 'device' && result && result.hasOwnProperty('readAfterWriteTime') && - entity.settings.retrieve_state + resolvedEntity.type === 'device' && result && result.hasOwnProperty('readAfterWriteTime') && + resolvedEntity.settings.retrieve_state ) { setTimeout(() => converter.convertGet(actualTarget, key, meta), result.readAfterWriteTime); } } else if (topic.type === 'get' && converter.convertGet) { - logger.debug(`Publishing get '${topic.type}' '${key}' to '${entity.name}'`); + logger.debug(`Publishing get '${topic.type}' '${key}' to '${resolvedEntity.name}'`); await converter.convertGet(actualTarget, key, meta); } else { logger.error(`No converter available for '${topic.type}' '${key}' (${json[key]})`); @@ -227,13 +225,13 @@ class EntityPublish extends Extension { } } catch (error) { const message = - `Publish '${topic.type}' '${key}' to '${entity.name}' failed: '${error}'`; + `Publish '${topic.type}' '${key}' to '${resolvedEntity.name}' failed: '${error}'`; logger.error(message); logger.debug(error.stack); /* istanbul ignore else */ if (settings.get().advanced.legacy_api) { - const meta = {friendly_name: entity.name}; + const meta = {friendly_name: resolvedEntity.name}; this.mqtt.publish( 'bridge/log', JSON.stringify({type: `zigbee_publish_error`, message, meta}), diff --git a/test/entityPublish.test.js b/test/publish.test.js similarity index 99% rename from test/entityPublish.test.js rename to test/publish.test.js index b43c294b..8d1d67ab 100644 --- a/test/entityPublish.test.js +++ b/test/publish.test.js @@ -21,7 +21,7 @@ const expectNothingPublished = () => { }) } -describe('Entity publish', () => { +describe('Publish', () => { let controller; beforeAll(async () => {