diff --git a/lib/extension/bridgeLegacy.js b/lib/extension/bridgeLegacy.js index d64e93a4a0..15c7be9415 100644 --- a/lib/extension/bridgeLegacy.js +++ b/lib/extension/bridgeLegacy.js @@ -63,7 +63,10 @@ class BridgeLegacy extends BaseExtension { assert(entity, `Entity '${message}' does not exist`); settings.whitelistDevice(entity.ID); logger.info(`Whitelisted '${entity.friendlyName}'`); - this.mqtt.log('device_whitelisted', {friendly_name: entity.friendlyName}); + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: 'device_whitelisted', message: {friendly_name: entity.friendlyName}}), + ); } catch (error) { logger.error(`Failed to whitelist '${message}' '${error}'`); } @@ -174,16 +177,18 @@ class BridgeLegacy extends BaseExtension { if (topic.split('/').pop() == 'get') { this.mqtt.publish(`bridge/config/devices`, JSON.stringify(devices), {}); } else { - this.mqtt.log('devices', devices); + this.mqtt.publish('bridge/log', JSON.stringify({type: 'devices', message: devices})); } } groups(topic, message) { - this.mqtt.log('groups', settings.getGroups().map((g) => { + const payload = settings.getGroups().map((g) => { const group = {...g}; delete group.friendlyName; return group; - })); + }); + + this.mqtt.publish('bridge/log', JSON.stringify({type: 'groups', message: payload})); } rename(topic, message) { @@ -223,7 +228,11 @@ class BridgeLegacy extends BaseExtension { const entity = this.zigbee.resolveEntity(to); const eventData = isGroup ? {group: entity.group} : {device: entity.device}; this.eventBus.emit(`${isGroup ? 'group' : 'device'}Renamed`, eventData); - this.mqtt.log(`${isGroup ? 'group' : 'device'}_renamed`, {from, to}); + + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `${isGroup ? 'group' : 'device'}_renamed`, message: {from, to}}), + ); } catch (error) { logger.error(`Failed to rename - ${from} to ${to}`); } @@ -254,7 +263,7 @@ class BridgeLegacy extends BaseExtension { const group = settings.addGroup(name, id); this.zigbee.createGroup(group.ID); - this.mqtt.log('group_added', name); + this.mqtt.publish('bridge/log', JSON.stringify({type: `group_added`, message: name})); logger.info(`Added group '${name}'`); } @@ -264,7 +273,7 @@ class BridgeLegacy extends BaseExtension { assert(entity && entity.type === 'group', `Group '${message}' does not exist`); settings.removeGroup(message); entity.group.removeFromDatabase(); - this.mqtt.log('group_removed', message); + this.mqtt.publish('bridge/log', JSON.stringify({type: `group_removed`, message})); logger.info(`Removed group '${name}'`); } @@ -291,7 +300,7 @@ class BridgeLegacy extends BaseExtension { if (!entity) { logger.error(`Cannot ${lookup[action][2]}, device '${message}' does not exist`); - this.mqtt.log(`device_${lookup[action][0]}_failed`, message); + this.mqtt.publish('bridge/log', JSON.stringify({type: `device_${lookup[action][0]}_failed`, message})); return; } @@ -306,7 +315,7 @@ class BridgeLegacy extends BaseExtension { this.state.remove(entity.settings.ID); logger.info(`Successfully ${lookup[action][0]} ${entity.settings.friendlyName}`); - this.mqtt.log(`device_${lookup[action][0]}`, message); + this.mqtt.publish('bridge/log', JSON.stringify({type: `device_${lookup[action][0]}`, message})); }; try { @@ -323,7 +332,7 @@ class BridgeLegacy extends BaseExtension { // eslint-disable-next-line logger.error(`See https://www.zigbee2mqtt.io/information/mqtt_topics_and_message_structure.html#zigbee2mqttbridgeconfigremove for more info`); - this.mqtt.log(`device_${lookup[action][0]}_failed`, message); + this.mqtt.publish('bridge/log', JSON.stringify({type: `device_${lookup[action][0]}_failed`, message})); } if (action === 'ban') { @@ -374,47 +383,78 @@ class BridgeLegacy extends BaseExtension { } if (type === 'deviceJoined') { - this.mqtt.log('device_connected', {friendly_name: resolvedEntity.name}); + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_connected`, message: {friendly_name: resolvedEntity.name}}), + ); } else if (type === 'deviceInterview') { if (data.status === 'successful') { if (resolvedEntity.definition) { const {vendor, description, model} = resolvedEntity.definition; const log = {friendly_name: resolvedEntity.name, model, vendor, description, supported: true}; - this.mqtt.log('pairing', 'interview_successful', log); + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `pairing`, message: 'interview_successful', meta: log}), + ); } else { - this.mqtt.log('pairing', 'interview_successful', - {friendly_name: resolvedEntity.name, supported: false}); + const meta = {friendly_name: resolvedEntity.name, supported: false}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `pairing`, message: 'interview_successful', meta}), + ); } } else if (data.status === 'failed') { - this.mqtt.log('pairing', 'interview_failed', {friendly_name: resolvedEntity.name}); + const meta = {friendly_name: resolvedEntity.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `pairing`, message: 'interview_failed', meta}), + ); } else { /* istanbul ignore else */ if (data.status === 'started') { - this.mqtt.log('pairing', 'interview_started', {friendly_name: resolvedEntity.name}); + const meta = {friendly_name: resolvedEntity.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `pairing`, message: 'interview_started', meta}), + ); } } } else if (type === 'deviceAnnounce') { - this.mqtt.log('device_announced', 'announce', {friendly_name: resolvedEntity.name}); + const meta = {friendly_name: resolvedEntity.name}; + this.mqtt.publish('bridge/log', JSON.stringify({type: `device_announced`, message: 'announce', meta})); } else { /* istanbul ignore else */ if (type === 'deviceLeave') { const name = resolvedEntity ? resolvedEntity.name : data.ieeeAddr; - this.mqtt.log('device_removed', 'left_network', {friendly_name: name}); + const meta = {friendly_name: name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_removed`, message: 'left_network', meta}), + ); } } } async touchlinkFactoryReset() { logger.info('Starting touchlink factory reset...'); - this.mqtt.log('touchlink', 'reset_started', {status: 'started'}); + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `touchlink`, message: 'reset_started', meta: {status: 'started'}}), + ); const result = await this.zigbee.touchlinkFactoryReset(); if (result) { logger.info('Successfully factory reset device through Touchlink'); - this.mqtt.log('touchlink', 'reset_success', {status: 'success'}); + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `touchlink`, message: 'reset_success', meta: {status: 'success'}}), + ); } else { logger.warn('Failed to factory reset device through Touchlink'); - this.mqtt.log('touchlink', 'reset_failed', {status: 'failed'}); + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `touchlink`, message: 'reset_failed', meta: {status: 'failed'}}), + ); } } } diff --git a/lib/extension/deviceBind.js b/lib/extension/deviceBind.js index 6f0d68f482..206351fdbe 100644 --- a/lib/extension/deviceBind.js +++ b/lib/extension/deviceBind.js @@ -61,26 +61,44 @@ class DeviceBind extends BaseExtension { `Successfully ${type === 'bind' ? 'bound' : 'unbound'} cluster '${cluster}' from ` + `'${sourceName}' to '${targetName}'`, ); - this.mqtt.log( - `device_${type}`, - {from: sourceName, to: targetName, cluster}, - ); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const message = {from: sourceName, to: targetName, cluster}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_${type}`, message}), + ); + } } catch (error) { logger.error( `Failed to ${type} cluster '${cluster}' from '${sourceName}' to ` + `'${targetName}' (${error})`, ); - this.mqtt.log( - `device_${type}_failed`, - {from: sourceName, to: targetName, cluster}, - ); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const message = {from: sourceName, to: targetName, cluster}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_${type}_failed`, message}), + ); + } } } } if (!attemptedToBindSomething) { logger.error(`Nothing to ${type} from '${sourceName}' to '${targetName}'`); - this.mqtt.log(`device_${type}_failed`, {from: sourceName, to: targetName}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const message = {from: sourceName, to: targetName}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_${type}_failed`, message}), + ); + } } } } diff --git a/lib/extension/entityPublish.js b/lib/extension/entityPublish.js index c0ec011a49..3e2968a567 100644 --- a/lib/extension/entityPublish.js +++ b/lib/extension/entityPublish.js @@ -59,7 +59,15 @@ class EntityPublish extends BaseExtension { const entity = this.zigbee.resolveEntity(entityName); if (!entity) { - this.mqtt.log('entity_not_found', {friendly_name: entityName}); + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const message = {friendly_name: entityName}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `entity_not_found`, message}), + ); + } + logger.error(`Entity '${entityName}' is unknown`); return; } @@ -211,7 +219,15 @@ class EntityPublish extends BaseExtension { `Publish '${topic.type}' '${key}' to '${entity.name}' failed: '${error}'`; logger.error(message); logger.debug(error.stack); - this.mqtt.log('zigbee_publish_error', message, {friendly_name: entity.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {friendly_name: entity.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `zigbee_publish_error`, message, meta}), + ); + } } usedConverters.push(converter); diff --git a/lib/extension/groups.js b/lib/extension/groups.js index fb8032f4c1..7f46856a7b 100644 --- a/lib/extension/groups.js +++ b/lib/extension/groups.js @@ -144,9 +144,16 @@ class Groups extends BaseExtension { if (!group || group.type !== 'group') { logger.error(`Group '${topicMatch[1]}' does not exist`); - this.mqtt.log( - `device_group_${type}_failed`, - {friendly_name: message, group: topicMatch[1], error: 'group doesn\'t exists'}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const payload = {friendly_name: message, group: topicMatch[1], error: 'group doesn\'t exists'}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_group_${type}_failed`, message: payload}), + ); + } + return; } } else if (topic.match(topicRegexRemoveAll)) { @@ -158,9 +165,16 @@ class Groups extends BaseExtension { const entity = this.zigbee.resolveEntity(message); if (!entity || !entity.type === 'device') { logger.error(`Device '${message}' does not exist`); - this.mqtt.log( - `device_group_${type}_failed`, - {friendly_name: message, group: topicMatch[1], error: 'entity doesn\'t exists'}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const payload = {friendly_name: message, group: topicMatch[1], error: 'entity doesn\'t exists'}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_group_${type}_failed`, message: payload}), + ); + } + return; } @@ -188,18 +202,42 @@ class Groups extends BaseExtension { logger.info(`Adding '${entity.name}' to '${group.name}'`); await entity.endpoint.addToGroup(group.group); settings.addDeviceToGroup(group.settings.ID, keys); - this.mqtt.log('device_group_add', {friendly_name: entity.name, group: group.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const payload = {friendly_name: entity.name, group: group.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_group_add`, message: payload}), + ); + } } else if (type === 'remove') { logger.info(`Removing '${entity.name}' from '${group.name}'`); await entity.endpoint.removeFromGroup(group.group); settings.removeDeviceFromGroup(group.settings.ID, keys); - this.mqtt.log('device_group_remove', {friendly_name: entity.name, group: group.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const payload = {friendly_name: entity.name, group: group.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_group_remove`, message: payload}), + ); + } } else { // remove_all logger.info(`Removing '${entity.name}' from all groups`); await entity.endpoint.removeFromAllGroups(); for (const settingsGroup of settings.getGroups()) { settings.removeDeviceFromGroup(settingsGroup.ID, keys); - this.mqtt.log('device_group_remove_all', {friendly_name: entity.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const payload = {friendly_name: entity.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `device_group_remove_all`, message: payload}), + ); + } } } } diff --git a/lib/extension/otaUpdate.js b/lib/extension/otaUpdate.js index 57e01b0fd9..e285337d0b 100644 --- a/lib/extension/otaUpdate.js +++ b/lib/extension/otaUpdate.js @@ -36,10 +36,15 @@ class OTAUpdate extends BaseExtension { if (available) { const message = `Update available for '${resolvedEntity.settings.friendly_name}'`; logger.info(message); - this.mqtt.log( - 'ota_update', message, - {status: 'available', device: resolvedEntity.settings.friendly_name}, - ); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: 'available', device: resolvedEntity.settings.friendly_name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `ota_update`, message, meta}), + ); + } } } @@ -77,7 +82,16 @@ class OTAUpdate extends BaseExtension { if (!device.definition || !device.definition.ota) { const message = `Device '${device.name}' does not support OTA updates`; logger.error(message); - this.mqtt.log('ota_update', message, {status: `not_supported`, device: device.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `not_supported`, device: device.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `ota_update`, message, meta}), + ); + } + return; } @@ -91,25 +105,59 @@ class OTAUpdate extends BaseExtension { if (type === 'check') { const message = `Checking if update available for '${device.name}'`; logger.info(message); - this.mqtt.log('ota_update', message, {status: `checking_if_available`, device: device.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `checking_if_available`, device: device.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `ota_update`, message, meta}), + ); + } + try { const available = await device.definition.ota.isUpdateAvailable(device.device, logger); const message=(available ? `Update available for '${device.name}'` : `No update available for '${device.name}'`); logger.info(message); - const meta = {status: available ? 'available' : 'not_available', device: device.name}; - this.mqtt.log('ota_update', message, meta); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: available ? 'available' : 'not_available', device: device.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `ota_update`, message, meta}), + ); + } + this.publishEntityState(device.device.ieeeAddr, {update_available: available}); this.lastChecked[device.device.ieeeAddr] = Date.now(); } catch (error) { const message = `Failed to check if update available for '${device.name}' (${error.message})`; logger.error(message); - this.mqtt.log('ota_update', message, {status: `check_failed`, device: device.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `check_failed`, device: device.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `ota_update`, message, meta}), + ); + } } } else { // type === 'update' const message = `Updating '${device.name}' to latest firmware`; logger.info(message); - this.mqtt.log('ota_update', message, {status: `update_in_progress`, device: device.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `update_in_progress`, device: device.name}; + this.mqtt.publish( + 'bridge/log', + JSON.stringify({type: `ota_update`, message, meta}), + ); + } + try { const onProgress = (progress, remaining) => { let message = `Update of '${device.name}' at ${progress}%`; @@ -118,7 +166,12 @@ class OTAUpdate extends BaseExtension { } logger.info(message); - this.mqtt.log('ota_update', message, {status: `update_progress`, device: device.name, progress}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `update_progress`, device: device.name, progress}; + this.mqtt.publish('bridge/log', JSON.stringify({type: `ota_update`, message, meta})); + } }; const from_ = await this.readSoftwareBuildIDAndDateCode(device.device, false); @@ -127,13 +180,22 @@ class OTAUpdate extends BaseExtension { const [fromS, toS] = [JSON.stringify(from_), JSON.stringify(to)]; const message = `Finished update of '${device.name}'` + (to ? `, from '${fromS}' to '${toS}'` : ``); logger.info(message); - const meta = {status: `update_succeeded`, device: device.name, from: from_, to}; - this.mqtt.log('ota_update', message, meta); this.publishEntityState(device.device.ieeeAddr, {update_available: false}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `update_succeeded`, device: device.name, from: from_, to}; + this.mqtt.publish('bridge/log', JSON.stringify({type: `ota_update`, message, meta})); + } } catch (error) { const message = `Update of '${device.name}' failed (${error.message})`; logger.error(message); - this.mqtt.log('ota_update', message, {status: `update_failed`, device: device.name}); + + /* istanbul ignore else */ + if (settings.get().advanced.legacy_api) { + const meta = {status: `update_failed`, device: device.name}; + this.mqtt.publish('bridge/log', JSON.stringify({type: `ota_update`, message, meta})); + } } } diff --git a/lib/mqtt.js b/lib/mqtt.js index b1171b89ae..3650cbffe2 100644 --- a/lib/mqtt.js +++ b/lib/mqtt.js @@ -111,16 +111,6 @@ class MQTT extends events.EventEmitter { this.client.publish(topic, payload, options, () => resolve()); }); } - - log(type, message, meta=null) { - const payload = {type, message}; - - if (meta) { - payload.meta = meta; - } - - this.publish('bridge/log', JSON.stringify(payload), {retain: false}); - } } module.exports = MQTT;