zigbee2mqtt
zigbee2mqtt copied to clipboard
Xiaomi ZNCLBL01LM: Template variable warning: 'dict object' has no attribute 'motor_state' when rendering '{{ value_json.motor_state }}'
What happened?
Very frequent error
Template variable warning: 'dict object' has no attribute 'motor_state' when rendering '{{ value_json.motor_state }}'. I thought I had resolved it in https://github.com/Koenkk/zigbee2mqtt/issues/14023, but that's not the case. I'm a bit lost, but because of this error automations from HA either run/stop running inconsistently. I'd love to help on this, but I don't understand how to change the payload to always include a value or where to find the information for this:
Given that
motor_stateis in the published payload, this seems to be a HA issue (or a very confusing error message)
I thought I had this fixed, but I don't. motor_state is not in the published payload, please see below
What did you expect to happen?
No errors
How to reproduce it (minimal and precise)
Connect the ZNCLBL01LM device to Zigbee2MQTT
Zigbee2MQTT version
1.27.2 commit: unknown, 1.28.2 commit: unknown
Adapter firmware version
0x26720700
Adapter
ConBee2/RaspBee2
Debug log
2022-11-21 10:22:28.624 DEBUG (MainThread) [homeassistant.components.mqtt.client] Received message on zigbee2mqtt/Bedroom Curtain Right: b'{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}'
2022-11-21 10:22:28.625 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_battery', 'name': 'Bedroom Curtain Right battery', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_battery)>} with default value '100' and Template("{{ value_json.battery }}")
2022-11-21 10:22:28.626 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_device_temperature', 'name': 'Bedroom Curtain Right device temperature', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_device_temperature)>} with default value '18' and Template("{{ value_json.device_temperature }}")
2022-11-21 10:22:28.626 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_action', 'name': 'Bedroom Curtain Right action', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_action)>} with default value 'None' and Template("{{ value_json.action }}")
2022-11-21 10:22:28.626 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_motor_state', 'name': 'Bedroom Curtain Right motor state', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_motor_state)>} with default value '' and Template("{{ value_json.motor_state }}")
2022-11-21 10:22:28.626 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'motor_state' when rendering '{{ value_json.motor_state }}'
2022-11-21 10:22:28.629 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_hooks_state', 'name': 'Bedroom Curtain Right hooks state', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_hooks_state)>} with default value 'locked' and Template("{{ value_json.hooks_state }}")
2022-11-21 10:22:28.630 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_target_position', 'name': 'Bedroom Curtain Right target position', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_target_position)>} with default value '72' and Template("{{ value_json.target_position }}")
2022-11-21 10:22:28.630 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'sensor.bedroom_curtain_right_power_source', 'name': 'Bedroom Curtain Right power source', 'this': <template TemplateStateFromEntityId(sensor.bedroom_curtain_right_power_source)>} with default value 'battery' and Template("{{ value_json.power_source }}")
2022-11-21 10:22:28.630 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'binary_sensor.bedroom_curtain_right_running', 'name': 'Bedroom Curtain Right running', 'this': <template TemplateStateFromEntityId(binary_sensor.bedroom_curtain_right_running)>} and Template("{{ value_json.running }}")
2022-11-21 10:22:28.631 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'binary_sensor.bedroom_curtain_right_charging', 'name': 'Bedroom Curtain Right charging', 'this': <template TemplateStateFromEntityId(binary_sensor.bedroom_curtain_right_charging)>} and Template("{{ value_json.charging }}")
2022-11-21 10:22:28.631 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'binary_sensor.bedroom_curtain_right_update_available', 'name': 'Bedroom Curtain Right update available', 'this': <template TemplateStateFromEntityId(binary_sensor.bedroom_curtain_right_update_available)>} and Template("{{ value_json['update']['state'] == "available" }}")
2022-11-21 10:22:28.631 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'position_open': 100, 'position_closed': 0, 'tilt_min': 0, 'tilt_max': 100, 'entity_id': 'cover.bedroom_curtain_right', 'name': 'Bedroom Curtain Right', 'this': <template TemplateStateFromEntityId(cover.bedroom_curtain_right)>} and Template("{{ value_json.position }}")
2022-11-21 10:22:28.631 DEBUG (MainThread) [homeassistant.components.mqtt.models] Rendering incoming payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T09:22:28.609Z","linkquality":255,"position":72,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":72,"update":{"state":"available"},"update_available":true,"voltage":3000}' with variables {'entity_id': 'cover.bedroom_curtain_right', 'name': 'Bedroom Curtain Right', 'this': <template TemplateStateFromEntityId(cover.bedroom_curtain_right)>} and Template("{% if not value_json.motor_state %} stopped {% else %} {{ value_json.motor_state }} {% endif %}")
2022-11-21 10:22:28.631 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'dict object' has no attribute 'motor_state' when rendering '{% if not value_json.motor_state %} stopped {% else %} {{ value_json.motor_state }} {% endif %}'
In case someone mistakes the "update":{"state":"available"} for me not updating the firmware, https://github.com/Koenkk/zigbee2mqtt/issues/13801#event-7331317095 describes this issue (on the Aqara side).
It looks like motor_state has only been added to the converter for the device and not as a key / converter in toZigbee - you will need to add an appropriate entry into there if this state can be set. There also isn't a key to convert the value returned from the device in fromZigbee either..
You may be able to get somewhere in the fromZigbee converters by adapting xiaomi_curtain_hagl04_status - in your previous PR, what is the difference between stopped and pause on the device state?
Thanks for your elaborate reply. Since motor_state cannot be controlled/sent (but only received), I take it I'll have to add it to fromZigbee?
I have tried two things;
- Looking at
xiaomi_curtain_hagl04_status. I understand it takes data from the clustergenMultistateOutputand converts the values from there. I don't seem to be able however to 'get' such an attribute report from within Zigbee2MQTT as there doesn't seem to be something like anattributeReportavailable:

- Since apart from owning several ZNCLBL01LM devices I also own several ZNJLBL01LM devices (and they don't seem to have the
motor_stateerrors, I looked at them too. It uses similar functionality infromZigbee(xiaomi_curtain_acn002_status) and very similar functionality inxiaomi.js.
So I created a custom converter, in order to start changing/reverse engineering (nothing special here, just copied the data from xiaomi.js and added fz.xiaomi_curtain_hagl04_status:
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const extend = require('zigbee-herdsman-converters/lib/extend');
const e = exposes.presets;
const ea = exposes.access;
const definition = {
zigbeeModel: ['lumi.curtain.acn003', 'lumi.curtain.agl001'],
model: 'ZNCLBL01LM',
vendor: 'Xiaomi',
whiteLabel: [{vendor: 'Xiaomi', model: 'CM-M01'}],
description: 'Aqara curtain driver E1',
fromZigbee: [fz.battery, fz.xiaomi_curtain_position_tilt, fz.aqara_opple, fz.power_source, fz.xiaomi_curtain_hagl04_status],
toZigbee: [tz.xiaomi_curtain_position_state, tz.ZNCLBL01LM_battery_voltage, tz.ZNCLBL01LM_hooks_state,
tz.power_source, tz.battery_percentage_remaining],
exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery().withAccess(ea.STATE_GET),
e.battery_voltage().withAccess(ea.STATE_GET),
e.device_temperature(),
e.action(['manual_open', 'manual_close']),
exposes.enum('motor_state', ea.STATE, ['stopped', 'opening', 'closing', 'pause'])
.withDescription('Motor state'),
exposes.binary('running', ea.STATE, true, false)
.withDescription('Whether the motor is moving or not'),
exposes.enum('hooks_state', ea.STATE_GET, ['unlocked', 'locked', 'locking', 'unlocking'])
.withDescription('Hooks state'),
exposes.numeric('target_position', ea.STATE).withUnit('%').withDescription('Target position'),
exposes.enum('power_source', ea.STATE_GET, ['battery', 'dc_source']).withDescription('The current power source'),
exposes.binary('charging', ea.STATE_GET, true, false).withDescription('The current charging state')],
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(1);
await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
await endpoint.read('aqaraOpple', [0x040B], {manufacturerCode: 0x115f});
await endpoint.read('aqaraOpple', [0x0428], {manufacturerCode: 0x115f});
await endpoint.read('genBasic', ['powerSource']);
await endpoint.read('closuresWindowCovering', ['currentPositionLiftPercentage']);
},
};
module.exports = definition;
Obviously this'll not work out of the box, so I'm trying to understand where to find the values that are being converted into the motor state and how to retreive them, in order to properly convert them.
I do see however that (at current) the motor_state is sometimes passed, and sometimes isn't:
Zigbee2MQTT:info 2022-11-21 13:05:08: MQTT publish: topic 'zigbee2mqtt/Bedroom Curtain Right', payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T12:05:08.742Z","linkquality":255,"motor_state":"stopped","position":0,"power_outage_count":7,"power_source":"battery","running":false,"state":"OPEN","target_position":0,"update":{"state":"available"},"update_available":true,"voltage":3000}'
Zigbee2MQTT:debug 2022-11-21 13:05:08: Received Zigbee message from 'Bedroom Curtain Right', type 'attributeReport', cluster 'aqaraOpple', data '{"1055":0}' from endpoint 1 with groupID null
Zigbee2MQTT:debug 2022-11-21 13:05:08: lumi.curtain.acn003,lumi.curtain.agl001: Processed data into payload {"target_position":100}
Zigbee2MQTT:info 2022-11-21 13:05:08: MQTT publish: topic 'zigbee2mqtt/Bedroom Curtain Right', payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T12:05:08.842Z","linkquality":255,"motor_state":"stopped","position":0,"power_outage_count":7,"power_source":"battery","running":false,"state":"OPEN","target_position":100,"update":{"state":"available"},"update_available":true,"voltage":3000}'
Zigbee2MQTT:debug 2022-11-21 13:05:09: Received Zigbee message from 'Bedroom Curtain Right', type 'attributeReport', cluster 'aqaraOpple', data '{"1057":0}' from endpoint 1 with groupID null
Zigbee2MQTT:debug 2022-11-21 13:05:09: lumi.curtain.acn003,lumi.curtain.agl001: Processed data into payload {"motor_state":"opening","running":true}
Zigbee2MQTT:info 2022-11-21 13:05:09: MQTT publish: topic 'zigbee2mqtt/Bedroom Curtain Right', payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T12:05:09.825Z","linkquality":255,"motor_state":"opening","position":0,"power_outage_count":7,"power_source":"battery","running":true,"state":"OPEN","target_position":100,"update":{"state":"available"},"update_available":true,"voltage":3000}'
Zigbee2MQTT:debug 2022-11-21 13:05:18: Received Zigbee message from 'Bedroom Curtain Right', type 'attributeReport', cluster 'aqaraOpple', data '{"1057":3}' from endpoint 1 with groupID null
Zigbee2MQTT:debug 2022-11-21 13:05:18: lumi.curtain.acn003,lumi.curtain.agl001: Processed data into payload {"running":false}
Zigbee2MQTT:info 2022-11-21 13:05:18: MQTT publish: topic 'zigbee2mqtt/Bedroom Curtain Right', payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T12:05:18.885Z","linkquality":255,"position":0,"power_outage_count":7,"power_source":"battery","running":false,"state":"OPEN","target_position":100,"update":{"state":"available"},"update_available":true,"voltage":3000}'
Zigbee2MQTT:debug 2022-11-21 13:05:18: Received Zigbee message from 'Bedroom Curtain Right', type 'attributeReport', cluster 'aqaraOpple', data '{"1055":35}' from endpoint 1 with groupID null
Zigbee2MQTT:debug 2022-11-21 13:05:18: lumi.curtain.acn003,lumi.curtain.agl001: Processed data into payload {"target_position":65}
Zigbee2MQTT:info 2022-11-21 13:05:18: MQTT publish: topic 'zigbee2mqtt/Bedroom Curtain Right', payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T12:05:18.916Z","linkquality":255,"position":0,"power_outage_count":7,"power_source":"battery","running":false,"state":"OPEN","target_position":65,"update":{"state":"available"},"update_available":true,"voltage":3000}'
Zigbee2MQTT:debug 2022-11-21 13:05:18: Received Zigbee message from 'Bedroom Curtain Right', type 'attributeReport', cluster 'closuresWindowCovering', data '{"currentPositionLiftPercentage":35}' from endpoint 1 with groupID null
Zigbee2MQTT:info 2022-11-21 13:05:18: MQTT publish: topic 'zigbee2mqtt/Bedroom Curtain Right', payload '{"action":null,"battery":100,"charging":false,"device_temperature":18,"hooks_state":"locked","last_seen":"2022-11-21T12:05:18.943Z","linkquality":255,"position":65,"power_outage_count":7,"power_source":"battery","running":false,"state":"CLOSE","target_position":65,"update":{"state":"available"},"update_available":true,"voltage":3000}'
What am I missing? I'm very sorry if I'm a complete noob or asking very stupid questions here.
I guess the first question to ask - do you have an aqara hub that you could temporarily join the device to? - We need to establish if motor_state is something that is actually reported by the device.
The above motor_state values may be a false posititve caused by Zigbee2MQTT caching a state from the use of an incorrect converter. That being said, attributeReport from aqaraOpple looks like an interesting one - without diving deep into how the device works in Z2M, it may be that one of these values is the motor_state..?
I guess the first question to ask - do you have an aqara hub that you could temporarily join the device to? - We need to establish if
motor_stateis something that is actually reported by the device.
No, I don't. I only have HA running Zigbee2MQTT (ConBee2/RaspBee2)
The above
motor_statevalues may be a false posititve caused by Zigbee2MQTT caching a state from the use of an incorrect converter. That being said,attributeReportfromaqaraOpplelooks like an interesting one - without diving deep into how the device works in Z2M, it may be that one of these values is themotor_state..?
I had thought about the caching as wel. When I had the issue initially (https://github.com/Koenkk/zigbee2mqtt/issues/14023) I was running a different HA install and after reinstall the issue occured again. Also, is it plausible that this could be caching given the fact that it is now running on a custom converter that I created today?
I figured to use attributeReport tto, but doesn't appear as a valid/existing Attribute, so I don't understand on how to retrieve the values:

I do have one of these devices and an Aqara hub, just not hooked up to anything at the moment.
I will see if I can get it set up in the next couple of days and see if the Aqara app reports motor_state if it does, I'll have a dig around (possibly do a Zigbee sniff) to see how it is reported
Just found some documentation that someone has done for Deconz: dresden-elektronik/deconz-rest-plugin#6469
It suggests that closuresWindowCovering (Cluster 0x0102) attribute 8 (not sure what this maps to in Z2M) may be where to derive the motor_state but I am not sure that it will give you the behaviour that you require...
I've tried to work through that, but I guess this is a little bit above what I understand...
Is it rude to tag @keith-kl here, as he has done most of the work in https://github.com/Koenkk/zigbee-herdsman-converters/pull/4307?
This is possibly going to be resolved by https://github.com/Koenkk/zigbee-herdsman-converters/pull/5104
Or by https://github.com/Koenkk/zigbee-herdsman-converters/issues/4943
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days
Too bad, but the issue is still very much there...