fix: dynamically create missing attribute objects in state_changed handler
When Home Assistant reports a new attribute for an entity after the initial sync (e.g. source_list or media_channel appearing when a media player becomes active), setState was called without a corresponding ioBroker object — causing 'has no existing object' warnings. Fix: check if the attribute object exists in hassObjects before calling setState. If missing, create it on-the-fly via setForeignObjectAsync before writing the state.
This commit is contained in:
+22
-1
@@ -664,7 +664,7 @@ class HassAdapter extends Adapter {
|
|||||||
|
|
||||||
this.hass.on('error', err => this.log.error(err));
|
this.hass.on('error', err => this.log.error(err));
|
||||||
|
|
||||||
this.hass.on('state_changed', entity => {
|
this.hass.on('state_changed', async entity => {
|
||||||
this.log.debug(`HASS-Message: State Changed: ${JSON.stringify(entity)}`);
|
this.log.debug(`HASS-Message: State Changed: ${JSON.stringify(entity)}`);
|
||||||
if (!entity || typeof entity.entity_id !== 'string') {
|
if (!entity || typeof entity.entity_id !== 'string') {
|
||||||
return;
|
return;
|
||||||
@@ -711,6 +711,27 @@ class HassAdapter extends Adapter {
|
|||||||
}
|
}
|
||||||
const attrId = attr.replace(this.FORBIDDEN_CHARS, '_').replace(/\.+$/, '_');
|
const attrId = attr.replace(this.FORBIDDEN_CHARS, '_').replace(/\.+$/, '_');
|
||||||
if (this.hassObjects[`${this.namespace}.${id}state`]) {
|
if (this.hassObjects[`${this.namespace}.${id}state`]) {
|
||||||
|
const fullAttrId = `${this.namespace}.${id}${attrId}`;
|
||||||
|
if (!this.hassObjects[fullAttrId]) {
|
||||||
|
// Attribute appeared after initial sync — create object dynamically
|
||||||
|
const common: ioBroker.StateCommon = {
|
||||||
|
...(knownAttributes[attr] as ioBroker.StateCommon | undefined),
|
||||||
|
name: attr.replace(/_/g, ' '),
|
||||||
|
read: true,
|
||||||
|
write: false,
|
||||||
|
role: 'state',
|
||||||
|
type: (mapTypes[typeof entity.attributes[attr]] ?? 'mixed') as ioBroker.CommonType,
|
||||||
|
};
|
||||||
|
const newObj: ioBroker.StateObject = {
|
||||||
|
_id: fullAttrId,
|
||||||
|
type: 'state',
|
||||||
|
common,
|
||||||
|
native: { entity_id: entity.entity_id, attr },
|
||||||
|
};
|
||||||
|
this.log.debug(`Creating missing attribute object ${fullAttrId}`);
|
||||||
|
await this.setForeignObjectAsync(fullAttrId, newObj);
|
||||||
|
this.hassObjects[fullAttrId] = newObj;
|
||||||
|
}
|
||||||
this.setState(id + attrId, { val, ack: true, lc, ts });
|
this.setState(id + attrId, { val, ack: true, lc, ts });
|
||||||
} else {
|
} else {
|
||||||
this.log.info(
|
this.log.info(
|
||||||
|
|||||||
Reference in New Issue
Block a user