mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-22 10:39:58 +00:00
Refactor device options retrieval
This commit is contained in:
+9
-17
@@ -121,14 +121,10 @@ class Controller {
|
||||
logger.info(`Currently ${devices.length} devices are joined:`);
|
||||
for (const device of devices) {
|
||||
const entity = this.zigbee.resolveEntity(device);
|
||||
logger.info(
|
||||
(entity.settings ? entity.settings.friendlyName : entity.device.ieeeAddr) +
|
||||
` (${entity.device.ieeeAddr}): ` +
|
||||
(entity.definition ?
|
||||
`${entity.definition.model} - ${entity.definition.vendor} ${entity.definition.description} ` :
|
||||
'Not supported ') +
|
||||
`(${entity.device.type})`,
|
||||
);
|
||||
const model = entity.definition ?
|
||||
`${entity.definition.model} - ${entity.definition.vendor} ${entity.definition.description}` :
|
||||
'Not supported';
|
||||
logger.info(`${entity.name} (${entity.device.ieeeAddr}): ${model} (${entity.device.type})`);
|
||||
}
|
||||
|
||||
// Enable zigbee join.
|
||||
@@ -209,9 +205,9 @@ class Controller {
|
||||
|
||||
async onZigbeeEvent(type, data) {
|
||||
const resolvedEntity = this.zigbee.resolveEntity(data.device || data.ieeeAddr);
|
||||
if (data.device && !resolvedEntity.settings && data.device.type !== 'Coordinator') {
|
||||
if (data.device && !settings.getDevice(data.device.ieeeAddr) && data.device.type !== 'Coordinator') {
|
||||
// Only deviceLeave doesn't have a device (not interesting to add to settings)
|
||||
resolvedEntity.settings = settings.addDevice(data.device.ieeeAddr);
|
||||
resolvedEntity.settings = {...settings.get().device_options, ...settings.addDevice(data.device.ieeeAddr)};
|
||||
}
|
||||
|
||||
const name = resolvedEntity && resolvedEntity.settings ? resolvedEntity.settings.friendlyName : null;
|
||||
@@ -286,13 +282,12 @@ class Controller {
|
||||
messagePayload = newState;
|
||||
}
|
||||
|
||||
const deviceOptions = settings.get().device_options;
|
||||
const options = {
|
||||
retain: utils.getObjectsProperty([resolvedEntity.settings, deviceOptions], 'retain', false),
|
||||
qos: utils.getObjectsProperty([resolvedEntity.settings, deviceOptions], 'qos', 0),
|
||||
retain: utils.getObjectProperty(resolvedEntity.settings, 'retain', false),
|
||||
qos: utils.getObjectProperty(resolvedEntity.settings, 'qos', 0),
|
||||
};
|
||||
|
||||
const retention = utils.getObjectsProperty([resolvedEntity.settings, deviceOptions], 'retention', false);
|
||||
const retention = utils.getObjectProperty(resolvedEntity.settings, 'retention', false);
|
||||
if (retention !== false) {
|
||||
options.properties = {messageExpiryInterval: retention};
|
||||
}
|
||||
@@ -318,9 +313,6 @@ class Controller {
|
||||
}
|
||||
|
||||
// filter mqtt message attributes
|
||||
if (deviceOptions.filtered_attributes) {
|
||||
deviceOptions.filtered_attributes.forEach((a) => delete messagePayload[a]);
|
||||
}
|
||||
if (resolvedEntity.settings.filtered_attributes) {
|
||||
resolvedEntity.settings.filtered_attributes.forEach((a) => delete messagePayload[a]);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
||||
const settings = require('../util/settings');
|
||||
const logger = require('../util/logger');
|
||||
const utils = require('../util/utils');
|
||||
@@ -1921,15 +1920,12 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
|
||||
onDeviceRemoved(device) {
|
||||
logger.debug(`Clearing Home Assistant discovery topic for '${device.ieeeAddr}'`);
|
||||
delete this.discovered[device.ieeeAddr];
|
||||
const resolvedEntity = this.zigbee.resolveEntity(device);
|
||||
if (resolvedEntity.definition) {
|
||||
logger.info(`Clearing Home Assistant discovery topic for '${device.ieeeAddr}'`);
|
||||
const deviceSettings = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
this.getConfigs(resolvedEntity.definition, deviceSettings).forEach((config) => {
|
||||
const topic = this.getDiscoveryTopic(config, device);
|
||||
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic);
|
||||
});
|
||||
for (const config of this.getConfigs(resolvedEntity)) {
|
||||
const topic = this.getDiscoveryTopic(config, device);
|
||||
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2043,17 +2039,14 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
|
||||
onDeviceRenamed(device) {
|
||||
logger.info(`Refreshing Home Assistant discovery topic for '${device.ieeeAddr}'`);
|
||||
logger.debug(`Refreshing Home Assistant discovery topic for '${device.ieeeAddr}'`);
|
||||
|
||||
// Clear before rename so Home Assistant use new friendly_name
|
||||
// https://github.com/Koenkk/zigbee2mqtt/issues/4096#issuecomment-674044916
|
||||
const resolvedEntity = this.zigbee.resolveEntity(device);
|
||||
if (resolvedEntity.definition) {
|
||||
const deviceSettings = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
this.getConfigs(resolvedEntity.definition, deviceSettings).forEach((config) => {
|
||||
const topic = this.getDiscoveryTopic(config, device);
|
||||
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic);
|
||||
});
|
||||
for (const config of this.getConfigs(resolvedEntity)) {
|
||||
const topic = this.getDiscoveryTopic(config, device);
|
||||
this.mqtt.publish(topic, null, {retain: true, qos: 0}, this.discoveryTopic);
|
||||
}
|
||||
|
||||
this.discover(resolvedEntity, true);
|
||||
@@ -2071,11 +2064,13 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
}
|
||||
|
||||
getConfigs(definition, deviceSettings) {
|
||||
let configs = mapping[definition.model].slice();
|
||||
getConfigs(resolvedEntity) {
|
||||
if (!resolvedEntity || !resolvedEntity.definition) return [];
|
||||
|
||||
let configs = mapping[resolvedEntity.definition.model].slice();
|
||||
configs.push(cfg.sensor_linkquality);
|
||||
|
||||
if (definition.hasOwnProperty('ota')) {
|
||||
if (resolvedEntity.definition.hasOwnProperty('ota')) {
|
||||
if (this.legacyApi) {
|
||||
configs.push(cfg.binary_sensor_update_available);
|
||||
}
|
||||
@@ -2085,7 +2080,7 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceSettings.hasOwnProperty('legacy') && !deviceSettings.legacy) {
|
||||
if (resolvedEntity.settings.hasOwnProperty('legacy') && !resolvedEntity.settings.legacy) {
|
||||
configs = configs.filter((c) => c !== cfg.sensor_click);
|
||||
}
|
||||
|
||||
@@ -2099,18 +2094,17 @@ class HomeAssistant extends Extension {
|
||||
discover(resolvedEntity, force=false) {
|
||||
// Check if already discoverd and check if there are configs.
|
||||
const {device, definition} = resolvedEntity;
|
||||
const deviceSettings = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
const discover = force || !this.discovered[device.ieeeAddr];
|
||||
if (!discover || !device || !definition || !mapping[definition.model] || !deviceSettings ||
|
||||
(deviceSettings.hasOwnProperty('homeassistant') && !deviceSettings.homeassistant)) {
|
||||
if (!discover || !device || !definition || !mapping[definition.model] ||
|
||||
(resolvedEntity.settings.hasOwnProperty('homeassistant') && !resolvedEntity.settings.homeassistant)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const friendlyName = deviceSettings.friendlyName;
|
||||
this.getConfigs(definition, deviceSettings).forEach((config) => {
|
||||
const friendlyName = resolvedEntity.settings.friendlyName;
|
||||
this.getConfigs(resolvedEntity).forEach((config) => {
|
||||
const topic = this.getDiscoveryTopic(config, device);
|
||||
const payload = {...config.discovery_payload};
|
||||
let stateTopic = `${settings.get().mqtt.base_topic}/${deviceSettings.friendlyName}`;
|
||||
let stateTopic = `${settings.get().mqtt.base_topic}/${friendlyName}`;
|
||||
if (payload.state_topic_postfix) {
|
||||
stateTopic += `/${payload.state_topic_postfix}`;
|
||||
delete payload.state_topic_postfix;
|
||||
@@ -2140,7 +2134,7 @@ class HomeAssistant extends Extension {
|
||||
payload.name = `${friendlyName}${nameSeparator}${config.object_id}`;
|
||||
|
||||
// Set unique_id
|
||||
payload.unique_id = `${deviceSettings.ID}_${config.object_id}_${settings.get().mqtt.base_topic}`;
|
||||
payload.unique_id = `${resolvedEntity.settings.ID}_${config.object_id}_${settings.get().mqtt.base_topic}`;
|
||||
|
||||
// Attributes for device registry
|
||||
payload.device = this.getDevicePayload(resolvedEntity);
|
||||
@@ -2237,7 +2231,7 @@ class HomeAssistant extends Extension {
|
||||
}
|
||||
|
||||
// Override configuration with user settings.
|
||||
if (deviceSettings.hasOwnProperty('homeassistant')) {
|
||||
if (resolvedEntity.settings.hasOwnProperty('homeassistant')) {
|
||||
const add = (obj) => {
|
||||
Object.keys(obj).forEach((key) => {
|
||||
if (['number', 'string', 'boolean'].includes(typeof obj[key])) {
|
||||
@@ -2252,10 +2246,10 @@ class HomeAssistant extends Extension {
|
||||
});
|
||||
};
|
||||
|
||||
add(deviceSettings.homeassistant);
|
||||
add(resolvedEntity.settings.homeassistant);
|
||||
|
||||
if (deviceSettings.homeassistant.hasOwnProperty(config.object_id)) {
|
||||
add(deviceSettings.homeassistant[config.object_id]);
|
||||
if (resolvedEntity.settings.homeassistant.hasOwnProperty(config.object_id)) {
|
||||
add(resolvedEntity.settings.homeassistant[config.object_id]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2285,11 +2279,9 @@ class HomeAssistant extends Extension {
|
||||
let clear = !resolvedEntity || !resolvedEntity.definition;
|
||||
|
||||
if (!clear) {
|
||||
const deviceSettings = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
const configs = this.getConfigs(resolvedEntity.definition, deviceSettings);
|
||||
const type = discoveryMatch[1];
|
||||
const objectID = discoveryMatch[3];
|
||||
clear = !configs.find((c) => c.type === type && c.object_id === objectID);
|
||||
clear = !this.getConfigs(resolvedEntity).find((c) => c.type === type && c.object_id === objectID);
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
|
||||
@@ -92,11 +92,11 @@ class EntityPublish extends Extension {
|
||||
definition = resolvedEntity.definition;
|
||||
target = resolvedEntity.endpoint;
|
||||
converters = resolvedEntity.definition.toZigbee;
|
||||
options = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
options = resolvedEntity.settings;
|
||||
} else {
|
||||
converters = groupConverters;
|
||||
target = resolvedEntity.group;
|
||||
options = {...settings.get().device_options, ...resolvedEntity.settings};
|
||||
options = resolvedEntity.settings;
|
||||
definition = resolvedEntity.group.members.map((e) => zigbeeHerdsmanConverters.findByDevice(e.getDevice()));
|
||||
}
|
||||
|
||||
|
||||
@@ -131,9 +131,6 @@ class Receive extends Extension {
|
||||
return;
|
||||
}
|
||||
|
||||
const debounce = resolvedEntity.settings.debounce || settings.get().device_options.debounce;
|
||||
const debounceIgnore = resolvedEntity.settings.debounce_ignore || settings.get().device_options.debounce_ignore;
|
||||
|
||||
// Convert this Zigbee message to a MQTT message.
|
||||
// Get payload for the message.
|
||||
// - If a payload is returned publish it to the MQTT broker
|
||||
@@ -155,8 +152,11 @@ class Receive extends Extension {
|
||||
}
|
||||
|
||||
// Check if we have to debounce
|
||||
if (debounce) {
|
||||
this.publishDebounce(data.device.ieeeAddr, payload, debounce, debounceIgnore);
|
||||
if (resolvedEntity.settings.debounce) {
|
||||
this.publishDebounce(
|
||||
data.device.ieeeAddr, payload, resolvedEntity.settings.debounce,
|
||||
resolvedEntity.settings.debounce_ignore,
|
||||
);
|
||||
} else {
|
||||
this.publishEntityState(data.device.ieeeAddr, payload);
|
||||
}
|
||||
@@ -165,8 +165,9 @@ class Receive extends Extension {
|
||||
const meta = {device: data.device, logger};
|
||||
let payload = {};
|
||||
converters.forEach((converter) => {
|
||||
const options = {...settings.get().device_options, ...settings.getDevice(data.device.ieeeAddr)};
|
||||
const converted = converter.convert(resolvedEntity.definition, data, publish, options, meta);
|
||||
const converted = converter.convert(
|
||||
resolvedEntity.definition, data, publish, resolvedEntity.settings, meta,
|
||||
);
|
||||
if (converted) {
|
||||
payload = {...payload, ...converted};
|
||||
}
|
||||
|
||||
+3
-9
@@ -111,14 +111,8 @@ function equalsPartial(object, expected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getObjectsProperty(objects, key, defaultValue) {
|
||||
for (const object of objects) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
return object[key];
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
function getObjectProperty(object, key, defaultValue) {
|
||||
return object.hasOwnProperty(key) ? object[key] : defaultValue;
|
||||
}
|
||||
|
||||
function getResponse(request, data, error) {
|
||||
@@ -180,7 +174,7 @@ module.exports = {
|
||||
getZigbee2mqttVersion,
|
||||
objectHasProperties,
|
||||
toSnakeCase,
|
||||
getObjectsProperty,
|
||||
getObjectProperty,
|
||||
getEndpointNames: () => endpointNames,
|
||||
isXiaomiDevice: (device) => {
|
||||
return device.modelID !== 'lumi.router' && xiaomiManufacturerID.includes(device.manufacturerID) &&
|
||||
|
||||
+6
-4
@@ -162,6 +162,7 @@ class Zigbee extends events.EventEmitter {
|
||||
`Wrong type '${typeof key}'`,
|
||||
);
|
||||
|
||||
const deviceOptions = settings.get().device_options;
|
||||
if (typeof key === 'string' || typeof key === 'number') {
|
||||
if (typeof key === 'number') {
|
||||
key = key.toString();
|
||||
@@ -216,12 +217,13 @@ class Zigbee extends events.EventEmitter {
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'device', device, endpoint, settings: entity, name: entity.friendlyName, definition,
|
||||
type: 'device', device, endpoint, settings: {...deviceOptions, ...entity},
|
||||
name: entity.friendlyName, definition,
|
||||
};
|
||||
} else {
|
||||
let group = this.getGroupByID(entity.ID);
|
||||
if (!group) group = this.createGroup(entity.ID);
|
||||
return {type: 'group', group, settings: entity, name: entity.friendlyName};
|
||||
return {type: 'group', group, settings: {...deviceOptions, ...entity}, name: entity.friendlyName};
|
||||
}
|
||||
} else if (key.constructor.name === 'Device') {
|
||||
const setting = settings.getEntity(key.ieeeAddr);
|
||||
@@ -229,7 +231,7 @@ class Zigbee extends events.EventEmitter {
|
||||
type: 'device',
|
||||
device: key,
|
||||
endpoint: key.endpoints[0],
|
||||
settings: setting,
|
||||
settings: {...deviceOptions, ...(setting || {})},
|
||||
name: setting ? setting.friendlyName : (key.type === 'Coordinator' ? 'Coordinator' : key.ieeeAddr),
|
||||
definition: zigbeeHerdsmanConverters.findByDevice(key),
|
||||
};
|
||||
@@ -238,7 +240,7 @@ class Zigbee extends events.EventEmitter {
|
||||
return {
|
||||
type: 'group',
|
||||
group: key,
|
||||
settings: setting,
|
||||
settings: {...deviceOptions, ...(setting || {})},
|
||||
name: setting ? setting.friendlyName : key.groupID,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user