Closed Luigi-01 closed 1 year ago
I created a DDF file since I ordered a few of these myself. This is actually the first time I ever looked into deCONZ or DDF files, but I managed to make basic features available:
What works
What doesn't work
Also when I change the target temperature on the thermostat directly I don't get the new value in Home Assistant. However I see the updated value in deCONZ GUI, so that may be an issue somewhere else.
I will look into it again when I got some spare time. However tips would be appreciated, I already read that Aqara Devices tend to reimagine the Zigbee Standard 😄
aqara-thermostat-e1.json
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "Thermostat E1",
"sleeper": false,
"status": "Draft",
"path": "/devices/aqara-thermostat-e1.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/mode",
"parse": {
"at": "0x001c",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
}
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"refresh.interval": 5
},
{
"name": "state/temperature",
"default": 0
},
{
"name": "state/valve",
"read": {
"at": "0x0012",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
},
"parse": {
"at": "0x0012",
"cl": "0x0201",
"ep": 0,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0000"
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0000",
"dt": "0x29",
"min": 1,
"max": 600,
"change": "0x00000014"
},
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
}
]
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x000A"
}
]
}
I have now this device, too. So I did some screenshots to complete the first post with the missing values.
I hope this helps.
Today I recieved an Essential 120112 Smart Home Radiator Thermostat. They are identical and connected straight with deConz. I can operate the valve with Domoticz, no isseus. Tonight or tomorrow I will check deConz and add the screen shots for this device.
Hereby some screen shots from the Essential 120112 Smart Home Radiator Thermostat. Physical they are the Same, Firmware/Software ?
@ulbrich-media thx for the DDF
What doesn't work
battery status (zigbee specification of the device says the default cluster 0x0001, attribute 0x0021 is not supported) external temperature sensor (with an aqara bridge you can connect the thermostat with an external sensor, I was hoping this is solved trough an attribute and not the bridge) schedule (didn't look into that, but there are attributes for that)
Also when I change the target temperature on the thermostat directly I don't get the new value in Home Assistant. However I see the updated value in deCONZ GUI, so that may be an issue somewhere else.
For the battery, the attribute 0x0020 seem working ? You have 31 as value The status is "Draft" better to use "Gold", because users always forget to change it for tests. You are using the attribute 0x0012 for state/valve, and this one is the heatpoint, I think it's for that the return don't update config/heatpoint.
For some danfoss device there is a special attribute for external sensor, like the 0x4015
@Luigi-01 no it's a different device and your is already supported.
Sorry, I only wanted to help. Not my intention to disturb the discussion. There they are physical the same, I thought it would be help full.
No problem, but take care your device is a tuya one, you can have so much clone of it, and you can have different device but with exactly the same look and buy at same seller.
I also added the DDF and had a look at the battery status. Therefore I looked at other zigbee devices with battery, so I tried to transfer the settings.
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"path": "/devices/e1_thermostat.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"parse": {
"at": "0x0020",
"cl": "0x0001",
"ep": 0,
"eval": "Item.val = Attr.val",
"fn": "zcl"
},
"default": 0
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/mode",
"parse": {
"at": "0x001c",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
}
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"refresh.interval": 5
},
{
"name": "state/temperature",
"default": 0
},
{
"name": "state/valve",
"read": {
"at": "0x0012",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
},
"parse": {
"at": "0x0012",
"cl": "0x0201",
"ep": 0,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0000"
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 1,
"max": 600,
"change": "0x00000014"
}
]
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x000A"
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0001",
"report": [
{
"at": "0x0020",
"dt": "0x20",
"min": 0,
"max": 31,
"change": "0x00000001"
}
]
}
]
}
I'm not sure if this is the correct way. I do not know very much about creating DDFs. The API tells about battery level 16:
"config": {
"battery": 0,
"heatsetpoint": 500,
"mode": "off",
"offset": 0,
"on": true,
"reachable": true
},
"etag": "ce7edd88dc6e43d07826b6e5e7af082d",
"lastannounced": null,
"lastseen": "2022-09-30T09:31Z",
"manufacturername": "LUMI",
"modelid": "lumi.airrtc.agl001",
"name": "Thermostat 11",
"state": {
"battery": 16,
"lastupdated": "2022-09-30T09:31:28.696",
"on": null,
"temperature": 2500,
"valve": 500
},
"swversion": "0.0.0_825",
"type": "ZHAThermostat",
"uniqueid": "54:ef:44:10:00:51:c3:5d-01-0201"
}
I definitely have no idea where this comes from. In Homeassistant the level is 0%.
Ha ^^, ok, I have understand.
Try this DDF
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"default": 0
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/mode",
"parse": {
"at": "0x001c",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
}
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"parse": {
"at": "0x0008",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val > 3;",
"fn": "zcl"
},
"read": {
"fn": "none"
}
},
{
"name": "state/temperature",
"default": 0
},
{
"name": "state/valve",
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 1,
"max": 600,
"change": "0x00000014"
}
]
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x000A"
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0001",
"report": [
{
"at": "0x0020",
"dt": "0x20",
"min": 300,
"max": 43200,
"change": "0x00000001"
}
]
}
]
}
I m still using the legacy code to get battery, but the good binding, I think heatpoint will work better too. Can need to wait a little for battery, I m using hudge values. Better to delete the device and re-include it (need to remake the binds)
I've used your DDF. After that I reincluded the device. The API is now:
"config": {
"battery": 0,
"heatsetpoint": 2000,
"mode": "off",
"offset": 0,
"on": true,
"reachable": true
},
"etag": "6b5f45c1803228268bb69b107b987af4",
"lastannounced": null,
"lastseen": "2022-10-02T07:00Z",
"manufacturername": "LUMI",
"modelid": "lumi.airrtc.agl001",
"name": "Thermostat 25",
"state": {
"lastupdated": "none",
"on": null,
"temperature": 0,
"valve": 0
},
"swversion": "0.0.0_0025",
"type": "ZHAThermostat",
"uniqueid": "54:ef:44:10:00:51:c3:5d-01-0201"
The Phoscon UI says, that the device is not reachable (but it is, so it isn't greyed out). And Home Assistant complains about the null state. Furthermore, in Home Assistant there are two temperature values. The first one is the target temperature, I think, this works well now. The second temperature, I think that's the measured value. Before the new DDF it was 25 degree (always constant at 25). With the new DDF, the value is still constant, but at 0 degree.
By the way, my thermostat isn't installed yet. It is on, but it's on my desk. I wanted to wait until it's working. I hope, that it doesn't make any difference.
The Phoscon UI says, that the device is not reachable And Home Assistant complains about the null
"reachable": true
But the value is good in the API .... You have tried to "resynchronise" HA ?
The local temperature is the attribute 0x0000 in the cluster 0x0201, can you try to read it ? If the api is updated in same time, it's a bind problem, else it's from the DDF and need to make this change for state/temperature
{
"name": "state/temperature",
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
}
},
Okay, I did a restart of the deconz addon and a reload of the integration. HA isn't complaining anymore. But in Phoscon it's "not reachable": Perhaps the null in the state block is the problem?
I read out the local temperature. The value is 2230. No changes in the api. So I added the part to the DDF (the cluster id was false before), did a reload of the DDF, a restart of the addon and a reload of the integration. Nothing changed. Then, I read it out manually again, and now the value is correct in the api and also in HA. So maybe there is still a bind problem? In Phoscon, the screen changed to:
Battery percentage is still 0 in HA and also in the api as you can see above.
Perhaps the null in the state block is the problem?
You mean the state/on ?
For me it's not a problem, we are missing the binding to update it, but you can force an update with reading the attribute 0x0008 on the thermostat cluster. I will set a defaut value in the DDF for it.
I have added a battery code full DDF too. Have removed the bind for the time cluster (other project don't use it)
BTW I m looking too all other attribute available on the manufacture cluster, so have added the child lock to test.
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"subdevices": [{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"parse": {
"at": "0x0020",
"cl": "0x0001",
"ep": 255,
"eval": "const vmin = 20; const vmax = 30; let bat = Attr.val; if (bat > vmax) { bat = vmax; } else if (bat < vmin) { bat = vmin; } bat = ((bat - vmin) / (vmax - vmin)) * 100; if (bat > 100) { bat = 100; } else if (bat <= 0) { bat = 1; } Item.val = bat;"
},
"default": 0
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/mode",
"parse": {
"at": "0x001c",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
}
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"parse": {
"at": "0x0008",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val > 3;",
"fn": "zcl"
},
"read": {
"fn": "none"
},
"default": false
},
{
"name": "state/temperature",
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
}
},
{
"name": "state/valve",
"default": 0
},
{
"name": "config/locked",
"awake": true,
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "{ Item.val = Item.val }",
"fn": "zcl",
"mf": "0x115f"
},
"read": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"write": {
"at": "0x0277",
"cl": "0xfcc0",
"dt": "0x10",
"ep": 1,
"eval": "Item.val",
"fn": "zcl",
"mf": "0x115f",
"state.timeout": 2
},
"default": false
}
]
}],
"bindings": [{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 300,
"max": 3600,
"change": "0x00000032"
}
]
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0001",
"report": [{
"at": "0x0020",
"dt": "0x20",
"min": 300,
"max": 43200,
"change": "0x00000001"
}]
}
]
}
Bind seem good for me, you have re-included the device, since the last time, for deconz remake all bind ? Have chnaged the reporting value to test
Okay, I took the new DDF, did a restart of the addon and reincluded the device. So now the battery percentage seems working, because the value is now 100% in Phoscon and also in HA. Thanks! The measured temperature was reported after pairing for about an hour (~ once every 20 minutes). After that, only if I read it manually. Then again for about an hour. Funny behaviour. So I did again a restart and reincluded the device. Same behaviour.
You mean the state/on ?
Yes, I meant. But state/on is false now and not null anymore.
After reincluding the device HA warns in the logs:
Logger: pydeconz.models.sensor.thermostat
Source: components/deconz/climate.py:154
First occurred: 09:33:34 (207 occurrences)
Last logged: 09:40:09
Unexpected thermostat mode None
If I change the thermostat mode in HA (and set it back to off), there are no more warnings.
At the config/lock: Unfortunately I don't know a simple way for copying/pasting the DDF into the HA deconz addon. So I have to reproduce the DDFs with the GUI. Didn't find a way to add the write block to the config/lock with the GUI. Therefore it's still missing in my DDF. Here the DDF I've used:
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"path": "/devices/e1_thermostat.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"parse": {
"at": "0x0020",
"cl": "0x0001",
"ep": 255,
"eval": "const vmin = 20; const vmax = 30; let bat = Attr.val; if (bat > vmax) { bat = vmax; } else if (bat < vmin) { bat = vmin; } bat = ((bat - vmin) / (vmax - vmin)) * 100; if (bat > 100) { bat = 100; } else if (bat <= 0) { bat = 1; } Item.val = bat;",
"fn": "zcl"
},
"default": 0
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/locked",
"awake": true,
"read": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Item.val;",
"fn": "zcl",
"mf": "0x115f"
},
"default": false
},
{
"name": "config/mode",
"parse": {
"at": "0x001c",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
}
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"refresh.interval": 5,
"read": {
"fn": "zcl"
},
"parse": {
"at": "0x0008",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val > 3;",
"fn": "zcl"
},
"default": false
},
{
"name": "state/temperature",
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
},
{
"name": "state/valve",
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 300,
"max": 3600,
"change": "0x00000032"
}
]
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0001",
"report": [
{
"at": "0x0020",
"dt": "0x20",
"min": 300,
"max": 43200,
"change": "0x00000001"
}
]
}
]
}
API looks now:
"27": {
"config": {
"battery": 100,
"heatsetpoint": 2000,
"locked": false,
"mode": "off",
"offset": 0,
"on": true,
"reachable": true
},
"etag": "d620752c5745eaa5895f0498f88f4ad3",
"lastannounced": "2022-10-03T16:21:04Z",
"lastseen": "2022-10-03T16:29Z",
"manufacturername": "LUMI",
"modelid": "lumi.airrtc.agl001",
"name": "Thermostat 27",
"state": {
"lastupdated": "2022-10-03T16:21:10.584",
"on": false,
"temperature": 2170,
"valve": 0
},
"swversion": "0.0.0_0025",
"type": "ZHAThermostat",
"uniqueid": "54:ef:44:10:00:51:c3:5d-01-0201"
}
What would the child lock attribute do?
The measured temperature was reported after pairing for about an hour (~ once every 20 minutes). After that, only if I read it manually. Then again for about an hour. Funny behaviour.
Ok, so I have no idea what happen, I need to search information on other forum.
Yes, I meant. But state/on is false now and not null anymore.
Yep, I have forced the false state, you can enable the bind of the attribute 0x0008 to test it, in fact the value become true when the value is > 3.
Unexpected thermostat mode None
Urf, this one NEED to be in binding, realy important, attribute 0x001c, if deconz don't update it fastly can set a defaut value, but for me "None" is a good defaut value, It mean "unknow yet" for me.
For config/locked (and not config/lock , this one is for door lock) it s the child protection, with your DDF you are not able to set it (need the write part) but if you change it manualy, you will have the result in the API.
I will make some search about the temperature that disable itself after 1 hour.
"min": 300,
"max": 3600,
"change": "0x00000032"
with this setting you need to have a report minimum every hour, or with a 0.2 °C change, maximum every 300s.
Perhaps if decreasing the 3600 value ?
the child lock attribute, than the temperature cannot changed manually. You can turn the knob, but the temperature will not change. By pressing the knop 3 seconds, the knop will not accept any input. By pressing the knop again 3 seconds it will unlock.
Here some further informations, maybe it helps. I've reincluded the device again. This is how the API looks a few minutes after pairing:
"27": {
"config": {
"battery": 0,
"heatsetpoint": 2050,
"locked": false,
"mode": null,
"offset": 0,
"on": true,
"reachable": true
},
"etag": "5934d4add914de00ad0081a08723834f",
"lastannounced": null,
"lastseen": "2022-10-04T08:05Z",
"manufacturername": "LUMI",
"modelid": "lumi.airrtc.agl001",
"name": "Thermostat 27",
"state": {
"lastupdated": "none",
"on": false,
"temperature": 0,
"valve": 0
},
"swversion": "0.0.0_0025",
"type": "ZHAThermostat",
"uniqueid": "54:ef:44:10:00:51:c3:5d-01-0201"
}
So I have to read the clusters manually (I always do this after pairing), then the battery value is correct again. For reading the clusters, it is necassary to play around with the device, like pressing or rotating the knob. Similiar behaviour as described here: https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Xiaomi:-Lost-devices-or-functional-issues What I didn't know until now, that I have to do the reading (and playing around) more often. For the most attributes it seems necessary to read it individually (especially for the lumic specific cluster). That's very time consuming, but here are some screenshots of the clusters that have changed:
There are still some attributes (Unknown), for that the reading has failed.
Reading the time attributes ends up in "failed 0xC3"
As you can see, the child lock attribute isn't available after all. I'm sorry for that.
Perhaps if decreasing the 3600 value ?
I've changed the binding to:
{
"at": "0x0000",
"dt": "0x29",
"min": 300,
"max": 3000,
"change": "0x0000000A"
}
Same behaviour, maybe I have to decrease it more. I think this behaviour is funny, because I can read the 0x0000 attribute individually. And it works every time - without any movements at the device. So I think, that isn't the problem. But why deconz doesn't read the value by itself? If I have a look to the logs (info_l2), I can see every second the following lines:
16:00:30:850 Idle timer triggered
16:00:30:852 Force read attributes for ZHAThermostat SensorNode Thermostat 27
16:00:30:854 Force binding of attribute reporting for node Thermostat 27
Urf, this one NEED to be in binding, realy important, attribute 0x001c, if deconz don't update it fastly can set a defaut value, but for me "None" is a good defaut value, It mean "unknow yet" for me.
Oh, yes, you're right. But after pairing (and reading out) I can see, that 0x001c has the value "auto". I think this option is in HA, too. Why deconz doesn't set this value to the api?
@Luigi-01: Thanks. I thought way too complicated.
As you can see, the child lock attribute isn't available after all. I'm sorry for that.
And if you use the @Luigi-01 procedure, pressing the knop 3 seconds, It will probably go ot "true" in the API.
I can see every second the following lines:
Interesting, you haven't an error message that can explain why the bind have failed ?
But why deconz doesn't read the value by itself?
It's possible, but better to use use reporting, if this one not working deconz will use poll, can force it using
{
"name": "state/temperature",
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"read": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"fn": "zcl"
},
"refresh.interval": 3660,
"default": 0
},
Refresh 3660 s.
Why deconz doesn't set this value to the api?
This value is not in binding, so this value is not reported by the device, except ofc if you read it yourself using deconz, add it in the binding list (have used defaut value used by deconz for temperature in attribute 0x0000)
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 1,
"max": 600,
"change": "0x00000032"
},
{
"at": "0x001c ",
"dt": "0x30",
"min": 1,
"max": 600
}
]
},
And if you use the @Luigi-01 procedure, pressing the knop 3 seconds, It will probably go ot "true" in the API.
I can activate the child lock at the device with the knob, that's right. But I think that's not an zigbee attribute anymore. See the new screenshots, it's unsupported/greyed out. That's what I meant. Same thing with the PI Heating Demand (0x0008 of thermostat cluster). We have used it for state/on, but with the new screenshots it's not supported.
Interesting, you haven't an error message that can explain why the bind have failed ?
No, there isn't. But over night it was reporting about one value every hour. Actually I didn't changed anything. Had a look to the history of the last days (to be sure), there wasn't a reporting for longer than an hour, exactly as described in the last posts. During the day, it was reporting more values. Didn't read it in deconz and didn't any movements at the device. Exciting. I hope, this is reproducible after reincluding.
It's possible, but better to use use reporting, if this one not working deconz will use poll, can force it using
I will wait before I add this, because maybe it's working without polling. I will reinclude it again to find it out.
This value is not in binding, so this value is not reported by the device, except ofc if you read it yourself using deconz, add it in the binding list (have used defaut value used by deconz for temperature in attribute 0x0000)
Will add the system mode to binding. Will see the results, probably after reincluding.
I wondered about the small number of supported attributes. If I see videos from people, who are using the thermostat with the aqara bridge, there are quite more functionalities. For example, the child lock, external temperature sensor, window detection and so on. Therefore I searched a little bit and found that the zigbee2mqtt project supports most of this features. So I think it has to be possible to control them through zigbee.
So I looked in the device request issue of zigbee2mqtt: https://github.com/Koenkk/zigbee2mqtt/issues/13993
In addition to that, I searched in the code of their zigbee library. I definitly don't know much about zigbee, but what I can see is, that the most of this features are in the lumi specific cluster. But they use some attribute numbers, that don't show up in deconz, e.g. 0x0277 for the child lock. I wasn't sure if the cluster in deconz and the one in zigbee2mqtt are the same. But there is one attribute, that is listed in both and it has the same value. It's the 0x00f7 in lumi specific cluster. Here the line at zigbee2mqtt: https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/devices/xiaomi.js#L77 So I assume, they are the same clusters. Is this correct? And why are the other attributes, that are listed there in the lines above, not in deconz, too?
I can activate the child lock at the device with the knob, that's right. But I think that's not an zigbee attribute anymore. See the new screenshots, it's unsupported/greyed out. That's what I meant.
Oups right, it s missing on the xml file, it s the attribute 0x0277. So not possible to see it using deconz, but can be see in the API with the DDF
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Item.val;",
"fn": "zcl",
"mf": "0x115f"
},
We have used it for state/on, but with the new screenshots it's not supported.
?? it was enabled here https://github.com/dresden-elektronik/deconz-rest-plugin/issues/6351#issue-1384701437 and disabled here https://github.com/dresden-elektronik/deconz-rest-plugin/issues/6351#issuecomment-1267300771
I wasn't sure if the cluster in deconz and the one in zigbee2mqtt are the same
Yeah they are ^^, and we can use them too, exaclty like the config/locked. This one was a test, if it work can add all others with the same way, but to write them, you need to edit the DDF manualy to add the "write" part.
We can add it in the xml file (general.xml) if you want to see them in deconz ?
?? it was enabled here #6351 (comment) and disabled here #6351 (comment)
Yes, I know. That's the problem I described. If you click the read button above the attribute tables, not all attributes are read with this devices. Didn't know that, so deconz shows them as available. But they aren't. It comes up, when you read them all individually. I realized this late. So only the newest screenshots show it correct. We have to change this part of the ddf.
Yeah they are ^^, and we can use them too, exaclty like the config/locked.
Really nice. I tried it with the config/locked. First it didn't work. But I changed your ddf part to:
{
"name": "config/locked",
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
}
Now it works perfect, I can see it in the api. Let's add the other attributes!
We can add it in the xml file (general.xml) if you want to see them in deconz ?
Yes, I think it would be useful. I will find a way to edit the ddf on console within the ha addon.
Yes, I know. That's the problem I described. If you click the read button above the attribute tables, not all attributes are read with this devices. Didn't know that, so deconz shows them as available. But they aren't. It comes up, when you read them all individually. I realized this late. So only the newest screenshots show it correct. We have to change this part of the ddf.
Ha yes, have same for doorlock, thoses device are not sleeper, but are not powered, so not so powerfull, we need to read attribute one by one, else the "read" button have same result, the device is not able to send all, adn deconz mark them as not available.
But I changed your ddf part to:
I don't see the change, just removed the "read" part ?
Yes, I think it would be useful
Try adding this part
<attribute-set id="0x0271" description="Smart Radiator Thermostat E1">
<attribute id="0x0271" name="Enabled" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0272" name="Mode" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0273" name="Window detection" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0274" name="Valve detection" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0277" name="Child lock off" type="u8" mfcode="0x115f" access="rw" required="m">
<description>Child lock off: 0 - false, 1 - true</description>
</attribute>
<attribute id="0x0279" name="Away temperature" type="u32" mfcode="0x115f" access="rw" required="m"> </attribute>
</attribute-set>
Around the line 4320 in the file description.xml
I don't see the change, just removed the "read" part ?
If the snippet is correct yes - and "eval": "Item.val = Attr.val;",
Is there a "mostly working" version of the DDF atm?
~I tried to rebuild one from your comments but it either does not work at all or now does not show sensor-temperature which used to work 2-3 days ago, related log eventually:~
~No thermostat sensor found for 0x54EF44100051D3B8, endpoint: 0x01
~
If the snippet is correct yes - and "eval": "Item.val = Attr.val;",
But this par tis already in the DDF ? and removing the "read" part have impact only if the device is polled .... I realy don't see why the previous DDF was not working.
To have the last DDf, I think it will be better to wait for @cameo77 share the modified one ^^.
To have the last DDf, I think it will be better to wait for @cameo77 share the modified one ^^.
exactly what I am waiting for ;)
I don't see the change, just removed the "read" part ?
There was no read part in my ddf, so no removal. I only changed the expression Item.val = Item.val;
to Item.val = Attr.val;
. I don't know if there is a difference theoretically, but it is only working with the second expression. Tested it twice.
Around the line 4320 in the file description.xml
I'm now able to edit the files on console within the ha addon. The only file with the name 'description.xml' that I can find is in /usr/share/deCONZ/webapp/description.xml
and has 43 lines. I think it's the wrong file. Is there another file with the same name? Or do you mean the 'general.xml'?
@dlueth: Here my current version of ddf:
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"path": "/devices/e1_thermostat.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"read": {
"at": "0x0020",
"cl": "0x0001",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0020",
"cl": "0x0001",
"ep": 1,
"eval": "const vmin = 20; const vmax = 30; let bat = Attr.val; if (bat > vmax) { bat = vmax; } else if (bat < vmin) { bat = vmin; } bat = ((bat - vmin) / (vmax - vmin)) * 100; if (bat > 100) { bat = 100; } else if (bat <= 0) { bat = 1; } Item.val = bat;",
"fn": "zcl"
},
"default": 0
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/locked",
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
"default": false
},
{
"name": "config/mode",
"parse": {
"at": "0x001c",
"cl": "0x0201",
"ep": 0,
"fn": "zcl"
}
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"refresh.interval": 5,
"read": {
"fn": "None"
},
"parse": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": false
},
{
"name": "state/temperature",
"read": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"fn": "zcl"
},
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
},
{
"name": "state/valve",
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 20,
"max": 300
},
{
"at": "0x001C",
"dt": "0x30",
"min": 1,
"max": 600
}
]
},
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0001",
"report": [
{
"at": "0x0020",
"dt": "0x20",
"min": 300,
"max": 43200
}
]
}
]
}
I think, it would be interesting to know which functions work for you and which do not. So please share it with us.
There was no read part in my ddf, so no removal. I only changed the expression Item.val = Item.val; to Item.val = Attr.val;. I don't know if there is a difference theoretically, but it is only working with the second expression. Tested it twice.
Ha fuck right, my bad, good catch. So to be able to change it using the API, the code can be
{
"name": "config/locked",
"read": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
"write": {
"at": "0x0277",
"cl": "0xfcc0",
"dt": "0x10",
"ep": 1,
"eval": "Item.val",
"fn": "zcl",
"mf": "0x115f"
},
"default": false
},
Is there another file with the same name? Or do you mean the 'general.xml'?
Right again, this file contain all attributes that can be see in deconz.
@cameo77 Your DDF works like the one I used before did. I added the changes from @Smanar's last comment here. Battery is, like it was before, always "0" , mode initially "unknown" and child/lock is nowhere to be seen. The rest, at least, seems to work.
@cameo77 OK, just did another test with your (unmodified) last DDF from here and added propsed changes to general.xml (which is very easy to achieve when using docker btw). I did remove the Radiator via phoscon this time and re-added it with the new DDF in place.
When re-adding it to OpenHAB this time ~i completely lost the "battery" channel and~ "mode" took a while to switch from "null" (meanwhile being unsettable) to "unkown" (becoming settable) and the "battery" channel took a while to occur (and still staying at 0%) . Child-Lock still missing as well
@dlueth can you take a look direcly in the API, idk if openHAb can display the whole json ? or in phoscon/help/API Information/sensor ?
Because we can't be sure if the problem is from the DDF with looking in third app.
This device is a lazy one, so can take time to be full working after a re-incusion. As long we don't change the binding, you can just make a "hot reaload" in the DDF editor or restart deconz
I m looking for "mode, it seem you can send request to the device but return are only enabled for some of them.
case 0x001C: // System Mode
{
if (sensor->modelId().startsWith(QLatin1String("SLR2")) || // Hive
sensor->modelId().startsWith(QLatin1String("SLR1b")) || // Hive
sensor->modelId().startsWith(QLatin1String("TH112")) || // Sinope
sensor->modelId().startsWith(QLatin1String("Zen-01")) || // Zen
sensor->modelId().startsWith(QLatin1String("AC201"))) // OWON
{
qint8 mode = attr.numericValue().s8;
QString modeSet;
if (mode == 0x01) { modeSet = QLatin1String("auto"); }
else if (mode == 0x03) { modeSet = QLatin1String("cool"); }
else if (mode == 0x04) { modeSet = QLatin1String("heat"); }
else if (mode == 0x05) { modeSet = QLatin1String("emergency heating"); }
else if (mode == 0x06) { modeSet = QLatin1String("precooling"); }
else if (mode == 0x07) { modeSet = QLatin1String("fan only"); }
else if (mode == 0x08) { modeSet = QLatin1String("dry"); }
else if (mode == 0x09) { modeSet = QLatin1String("sleep"); }
else { modeSet = QLatin1String("off"); }
item = sensor->item(RConfigMode);
if (item && !item->toString().isEmpty() && item->toString() != modeSet)
{
item->setValue(modeSet);
enqueueEvent(Event(RSensors, RConfigMode, sensor->id(), item));
configUpdated = true;
}
}
so strange it can work for this device ? We probably need to make something like and adding a "parse" part. If someone can confirm it relay don't work at all ?
{
"name": "config/mode",
"default" : "off",
"values": [
["\"off\"", "off mode"],
["\"auto\"", "Auto mode"],
["\"cool\"", "Cool mode"],
["\"heat\"", "Heat mode"],
]
},
For the battery, probably need to wait a little.
I have read a lot of code (of zigbee2mqtt, their zigbee library, deconz and ha integration), so now I probably know more. First about the 'general.xml': Your code is working well @smanar. I renamed some of the attributes and added the last two attributes. I tried to add values for 'preset', but it has no effect. What's wrong? Or is it better in ddf? Here my current version:
<attribute-set id="0x0271" description="Smart Radiator Thermostat E1">
<attribute id="0x0271" name="Enabled" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0272" name="Preset" type="u8" mfcode="0x115f" access="rw" required="m" default="0">
<value name="manual" value="0"></value>
<value name="auto" value="1"></value>
<value name="away" value="2"></value>
</attribute>
<attribute id="0x0273" name="Window detection" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0274" name="Valve fault detection" type="u8" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x0277" name="Child lock on" type="u8" mfcode="0x115f" access="rw" required="m">
<description>Child lock on: 0 - false, 1 - true</description>
</attribute>
<attribute id="0x0279" name="Away temperature" type="u32" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x027b" name="Calibration" type="u8" mfcode="0x115f" access="r" required="m"> </attribute>
<attribute id="0x027e" name="External sensor" type="u8" mfcode="0x115f" access="r" required="m"> </attribute>
</attribute-set>
About the battery problem: According to the zigbee2mqtt project and my tests, I assume, that the battery value isn't reported by the device itself. So we have to use poll for reading it. See the config/battery part in my current ddf below. It is working for me (it lasts 5 minutes after pairing until correct value). I'm thinking about setting the default value to 100 percent, but I don't know if it's useful.
About the mode and on: Again, according to the zigbee2mqtt project and my tests, I assume, that you can set if the device is heating or not only with the 0x0271 in lumi specific cluster. Using this the engine rotates the valve (system mode from thermostat cluster doesn't have an effect btw). Furthermore with preset I can set heating "mode" like 'auto', 'manual' or 'away'. So now the question is, how to implement this in ddf. Tried it with state/on and config/preset (see in the ddf). I can see it's working in the api, but I don't know if it's correct for the softwares that are using the api? And do we need a read or write part?
My current ddf:
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"path": "/devices/e1_thermostat.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"refresh.interval": 300,
"read": {
"at": "0x0020",
"cl": "0x0001",
"ep": 1,
"fn": "zcl"
},
"parse": {
"at": "0x0020",
"cl": "0x0001",
"ep": 1,
"eval": "const vmin = 20; const vmax = 30; let bat = Attr.val; if (bat > vmax) { bat = vmax; } else if (bat < vmin) { bat = vmin; } bat = ((bat - vmin) / (vmax - vmin)) * 100; if (bat > 100) { bat = 100; } else if (bat <= 0) { bat = 1; } Item.val = bat;",
"fn": "zcl"
},
"default": 0
},
{
"name": "config/heatsetpoint",
"default": 0
},
{
"name": "config/locked",
"read": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
"default": false
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/preset",
"parse": {
"at": "0x0272",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
}
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"refresh.interval": 5,
"read": {
"fn": "None"
},
"parse": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
}
},
{
"name": "state/temperature",
"read": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"fn": "zcl"
},
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
},
{
"name": "state/valve",
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 20,
"max": 300
}
]
}
]
}
@dlueth: Interesting, thanks. Can you see the child lock attribute in the api as @smanar described? I can't use it in ha, but I can see it in the api. How the battery value behaves with the new ddf (maybe it will last 5 minutes after pairing)?
@cameo77
can you take a look direcly in the API, idk if openHAb can display the whole json ? or in phoscon/help/API Information/sensor ?
{ "config": { "battery": 0, "heatsetpoint": 2000, "locked": false, "mode": "heat", "offset": 75, "on": true, "reachable": true }, "etag": "867dce4e693e6baa6b7a85d6c28fbbec", "lastannounced": "2022-10-09T05:49:08Z", "lastseen": "2022-10-09T10:46Z", "manufacturername": "LUMI", "modelid": "lumi.airrtc.agl001", "name": "Aqara: Thermostat", "state": { "lastupdated": "2022-10-09T10:46:22.436", "on": true, "temperature": 2200, "valve": 0 }, "swversion": "0.0.0_0025", "type": "ZHAThermostat", "uniqueid": "54:ef:44:10:00:51:d3:b8-01-0201" }
@cameo77 And after applying your current DDF + XML changes and waiting for some minutes:
{ "config": { "battery": 100, "heatsetpoint": 2000, "locked": false, "offset": 75, "on": true, "preset": null, "reachable": true }, "etag": "5d401028b567e5a532d35f9378552fd6", "lastannounced": null, "lastseen": "2022-10-09T10:56Z", "manufacturername": "LUMI", "modelid": "lumi.airrtc.agl001", "name": "Aqara: Thermostat", "state": { "lastupdated": "2022-10-09T10:56:11.361", "on": true, "temperature": 2220, "valve": 0 }, "swversion": "0.0.0_0025", "type": "ZHAThermostat", "uniqueid": "54:ef:44:10:00:51:d3:b8-01-0201" }
I tried to add values for 'preset', but it has no effect
It's because of the type, from the z2m link this value is a u8, so a number.
<value name="manual" value="0"></value>
is for enum8, a list of value
You can try to cheat using enum8, but deconz will use this type in the request, so if the device whant a u8 the request will not work, you can describe all possible value in the <description>
For the battery, I don't see the polling in your DDF, it a field like "refresh.interval": 3600
, but after a time if the report is not working deconz use poll itself.
For the working mode, there is a debate about "mode" and "preset". We are using HA rule, so mode can be only "off", "auto" and "manu". All other can be possible with "preset"' Some device have only "mode" some other have only "preset" (it's a jungle, thx tuya)
If you have only thoses 3 mode I think it's better to use them in "mode" than "preset"
{
"name": "config/mode",
"parse": {
"at": "0x0272",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = ['manu', 'auto', 'off'][Attr.val]",
"fn": "zcl",
"mf": "0x115f"
},
"read": {
"at": "0x0272",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
"write": {
"at": "0x0272",
"cl": "0xfcc0",
"dt": "0x20",
"ep": 1,
"eval": "if (Item.val == 'manu') { 0 } else if (Item.val == 'auto') { 1 } else {2}",
"fn": "zcl",
"mf": "0x115f"
},
},
Tried it with state/on and config/preset (see in the ddf)
State/on is read only for sensor, writable value are in config/x
I can see it's working in the api, but I don't know if it's correct for the softwares that are using the api?
cf my previous comment
And do we need a read or write part?
Yes you need the "write" part toi be able to write the value using the API.
But it mean too we can remove the bind for the attribute 0x001C ? if we use only the one in the Xiaomi cluster ? And we can remove too the config/preset ?
Btw, any idea if the offset is really taken into consideration by the radiator?
Okay, there were a few changes in z2m today. So I added the new attributes to the 'general.xml' and changed it according to your description. So here my current version of the 'general.xml':
<attribute-set id="0x0271" description="Smart Radiator Thermostat E1">
<attribute id="0x0271" name="Heating state" type="u8" mfcode="0x115f" access="rw" required="m">
<description>Heating state: 0 - off, 1 - on</description>
</attribute>
<attribute id="0x0272" name="Preset" type="u8" mfcode="0x115f" access="rw" required="m" default="0">
<description>Preset: 0 - manual, 1 - auto, 2 - away</description>
</attribute>
<attribute id="0x0273" name="Window detection" type="u8" mfcode="0x115f" access="rw" required="m">
<description>Window detection: 0 - off, 1 - on</description>
</attribute>
<attribute id="0x0274" name="Valve fault detection" type="u8" mfcode="0x115f" access="rw" required="m">
<description>Valve fault detection: 0 - off, 1 - on</description>
</attribute>
<attribute id="0x0275" name="Valve fault alarm" type="u8" mfcode="0x115f" access="r" required="m">
<description>Valve fault alarm: 0 - false, 1 - true</description>
</attribute>
<attribute id="0x0277" name="Child lock on" type="u8" mfcode="0x115f" access="rw" required="m">
<description>Child lock on: 0 - false, 1 - true</description>
</attribute>
<attribute id="0x0279" name="Away preset temperature" type="u32" mfcode="0x115f" access="rw" required="m"> </attribute>
<attribute id="0x027a" name="Window open" type="u8" mfcode="0x115f" access="r" required="m">
<description>Window open: 0 - false, 1 - true</description>
</attribute>
<attribute id="0x027b" name="Calibrated" type="u8" mfcode="0x115f" access="r" required="m">
<description>Calibrated: 0 - false, 1 - true</description>
</attribute>
<attribute id="0x027e" name="External sensor" type="u8" mfcode="0x115f" access="r" required="m">
<description>Temperature sensor: 0 - internal, 1 - external</description>
</attribute>
<attribute id="0x040a" name="Battery" type="u8" mfcode="0x115f" access="r" required="m"> </attribute>
</attribute-set>
I don't see the polling in your DDF
There was a "refresh.interval": 300,
at the beginning of config/battery.
But, as you can see, there is now a battery value in lumi specific cluster (thx aqara...). So I changed the config/battery to the new attribute. Now the value appears instantly after pairing. I don't know if it's updated without bind/poll.
{
"name": "config/battery",
"read": {
"at": "0x040a",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x040a",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
"default": 0
},
We are using HA rule, so mode can be only "off", "auto" and "manu".
Okay, the thermostat has two attributes for control. With the 0x0271 I can set if it's heating or not (on/off). And with the 0x0272 I can set the preset (manual/auto/away). If I look to your ddf part, I'm not sure if it works correct, because the 0x0272 has no off functionality. I think, we need both attributes. Not sure, but according to ha documentation and deconz integration code, it could be possible to use both: What do you think about? I would try to use config/preset for 0x0272. But is there an config option that I can use for 0x0271 instead of config/mode (because 0x0271 has no auto value)?
State/on is read only for sensor, writable value are in config/x
Yes you need the "write" part toi be able to write the value using the API.
Thanks! I will change it.
But it mean too we can remove the bind for the attribute 0x001C ? if we use only the one in the Xiaomi cluster ?
Is removed. Binding now only for occupied heating point and local temp.
@dlueth: Okay, child lock is visible in the api. So I assume, that's not a problem of deconz.
Btw, any idea if the offset is really taken into consideration by the radiator?
unfortunately not. maybe @smanar? funny, that you have an offset in the api and I haven't.
@Smanar when using your DDF it is visible in phoscon, not when using @cameo77 's
I do have an offset because my openhab calculates the delta of thermostat's sensor vs external sensor and sets it ;)
Btw, I will receive some essential radiators tomorrow most likely, they are the same as Aqara but have been supported before by deconz
Now the value appears instantly after pairing. I don't know if it's updated without bind/poll.
Good question, from my memory Xiaomi cluster don't need bind/report.
when using your DDF it is visible in phoscon, not when using @cameo77 's
Hu ? On my side I m using the last gived by him too, perhaps there is a typo in one of them ? Phoscon is not a "reference" too, better to check on HA or direclty in the API.
I think, we need both attributes.
So the attribute that make on/off in "mode", and the attribute that make manual/auto/away in "preset" ?
What do you think about? I would try to use config/preset for 0x0272. But is there an config option that I can use for 0x0271 instead of config/mode (because 0x0271 has no auto value)?
yes, config/mode is device dependent, there is some device with just on/off, like some wall mounted thermostat, they have all managed by "preset", "mode" is just to turn the device "on" or "off". "Auto" will just not working in HA
Btw, any idea if the offset is really taken into consideration by the radiator?
I m taking a look in the code, for ZHAThermostat device, this request use a zigbee request so send a "calibration" value to the device. It's the attribute 0x0010 in the thermostat cluster. And yes it seem this field can be used by legacy code for all ZHAThermostat.
Good question, from my memory Xiaomi cluster don't need bind/report.
Well, I would also not add bind/report.
So the attribute that make on/off in "mode", and the attribute that make manual/auto/away in "preset" ?
Exactly. Both are necessary, I think.
yes, config/mode is device dependent, there is some device with just on/off, like some wall mounted thermostat, they have all managed by "preset", "mode" is just to turn the device "on" or "off". "Auto" will just not working in HA
So I should use config/mode and config/preset for them, shouldn't I? I read some code of the deconz integration. It's interesting. Mode 'auto' is only added if there is config/mode in api (look here). Accordingly, if there isn't, only the modes 'off' and 'heat' exist. Actually that's what we would need. So the question is which item we could use instead. For that I looked into the function, that sets the mode. Accordingly it is the config/on, take a look at here. But config/on is managed internally, as the ddf editor tells. Or could we use it? I'm really not sure if that would work. So let me know your thoughts about. Otherwise we simply use config/mode and setting 'auto' has no effect.
I read some code of the deconz integration. It's interesting. Mode 'auto' is only added if there is config/mode in api (look here). Accordingly, if there isn't, only the modes 'off' and 'heat' exist. Actually that's what we would need.
IDK how work this code, but if there is no "config/mode", you will have no mode at all, so no more "heat" and "off" no ? If I m right you have a widget in HA with auto/off/heat, and this one work only with "config/mode" so if you want to use this one you need the "config/mode" No ? even "auto is not working.
"config/on" is used for rules, can't use this one.
There is "config/setvalve" as bool, but I think the integration in HA will be better natively is using "config/mode"
The more I was reading, the more I was tending to use config/mode. So let's proceed with it. Here is my ddf part:
{
"name": "config/mode",
"read": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = ['off', 'heat'][Attr.val];",
"fn": "zcl",
"mf": "0x115f"
},
"write": {
"at": "0x0271",
"cl": "0xfcc0",
"dt": "0x20",
"ep": 1,
"eval": "if (Item.val == 'off') { 0 } else if (Item.val == 'heat') { 1 }",
"fn": "zcl",
"mf": "0x115f"
}
},
Reading works, but writing doesn't (through home assistant). Did a restart of the addon and reinclude of the device. Do you see the error?
dt = 0x20, it's the correct type for u8 All the rest seem fine for me
I think you can take a look in same time in logs with flag
On some DDF there is too "state.timeout": 2
but I don't think it will be usefull on this one, a TRV is not a deep sleeping device.
Okay, thank you. With DDF I can't see a evaluation of the write part in the logs. With info and info_l2, I can see the following lines while changing config/mode through ha:
09:35:03:489 Websocket 172.30.32.1:54536 send message: {"config":{"battery":100,"heatsetpoint":2200,"locked":false,"mode":"off","offset":0,"on":true,"preset":"manual","reachable":true},"e":"changed","id":"27","r":"sensors","t":"event","uniqueid":"54:ef:44:10:00:51:c3:5d-01-0201"} (ret = 225)
09:35:03:927 No thermostat sensor found for 0x54EF44100051C35D, endpoint: 0x01
09:35:03:930 Websocket 172.30.32.1:54536 send message: {"e":"changed","id":"27","r":"sensors","state":{"lastupdated":"2022-10-11T07:35:03.927","on":true,"temperature":2260,"windowopen":"false"},"t":"event","uniqueid":"54:ef:44:10:00:51:c3:5d-01-0201"} (ret = 196)
No interesting logs with ZCL.
Btw, received my _TYST11_jeaxp72v (Essentials Radiator Premium) yesterday which is essentially the same device. These connect fine but seem to share issues regarding mode/preset. Mode is shown as "unknown" and seems to be not settable. Child lock is also missing there. Might this issue fix that as well?
There are realy not same device, one is using the tuya cluster, the other the Xiaomi one.
With DDF I can't see a evaluation of the write part in the logs.
Not normal ... Childlock is working (the write stuff) ? nothing in logs too ?
09:35:03:927 No thermostat sensor found for 0x54EF44100051C35D, endpoint: 0x01
Not normal too. It mean the code haven't found ZHAThermostat for endpoint 01 and MAC adresss 0x54EF44100051C35D and it's exacly that
"uniqueid":"54:ef:44:10:00:51:c3:5d-01-0201"
The device type is a ZHAThermostat ? But this part impact only return, not send request.
Childlock is working (the write stuff) ? nothing in logs too ?
Childlock doesn't appear in ha. I can only see it in the api. So I don't know if writing works.
The device type is a ZHAThermostat ?
Yes. Didn't change that. It's still the same as in the ddfs in my posts above.
"uniqueid":"54:ef:44:10:00:51:c3:5d-01-0201"
MAC address seems to be correct, Endpoint too. But why 0201? It's the thermostat cluster, not lumi specific, I think.
Is there a way to call the api through url/http request? Would be interesting if the error is by ha or by deconz
Found a way to control the api through command line and tried to write config/mode -> same behaviour as before Added 0xfcc0 to uuid (at the top of the ddf) -> can't see the 'not found' log anymore, but value isn't written Added binding for mode attribute -> 'not found' log appears periodically, value isn't written
So I think, it's a problem in deconz. Beyond that I do not know anymore than before.
09:35:03:927 No thermostat sensor found for 0x54EF44100051C35D, endpoint: 0x01
Ok, so Swoops have found the problem, we miss the fingerprint
"path": "/devices/e1_thermostat.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"fingerprint": {
"profile": "0x0104",
"device": "0x0301",
"endpoint": "0x01",
"in": [
"0x0000",
"0xFCC0",
"0x0201"
]
},
"items": [
{
"name": "attr/id"
You can use a REST client to edit value yourself https://dresden-elektronik.github.io/deconz-rest-doc/getting_started/
Else just curl
curl -H 'Content-Type: application/json' -X PUT -d '{"duration": 90}' http://192.168.1.1:80/api/12345678/sensors/16/config
But strange Childlock don't appear in HA, its not something new.
Okay, I have added the fingerprint to my ddf. There is no 'not found' log anymore, but writing doesn't work through the api. Here some logs while setting mode through ha (with info and info_l2):
11:10:27:072 add task 13644 type 37 to 0x54EF44100051C35D cluster 0x0201 req.id 146
11:10:27:154 Websocket 172.30.32.1:49136 send message: {"config":{"battery":100,"heatsetpoint":700,"locked":false,"mode":"heat","offset":0,"on":true,"preset":"manual","reachable":true},"e":"changed","id":"27","r":"sensors","t":"event","uniqueid":"54:ef:44:10:00:51:c3:5d-01-0201"} (ret = 225)
Still no evaluation to see in ddf log, no usefully data in zcl.
Edit: And here the error log from home assistant while setting preset:
[547364435328] {'address': '/sensors/27/config/preset', 'description': 'Could not set attribute', 'type': 608}
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 202, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1738, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1775, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 207, in handle_service
await service.entity_service_call(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 678, in entity_service_call
future.result() # pop exception if have
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 931, in async_request_call
await coro
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 715, in _handle_entity_call
await result
File "/usr/src/homeassistant/homeassistant/components/deconz/climate.py", line 205, in async_set_preset_mode
await self.gateway.api.sensors.thermostat.set_config(
File "/usr/local/lib/python3.10/site-packages/pydeconz/interfaces/sensors.py", line 560, in set_config
return await self.gateway.request_with_retry(
File "/usr/local/lib/python3.10/site-packages/pydeconz/gateway.py", line 142, in request_with_retry
return await self.request(method, path, json)
File "/usr/local/lib/python3.10/site-packages/pydeconz/gateway.py", line 167, in request
response: dict[str, Any] = await self._request(
File "/usr/local/lib/python3.10/site-packages/pydeconz/gateway.py", line 194, in _request
_raise_on_error(response)
File "/usr/local/lib/python3.10/site-packages/pydeconz/gateway.py", line 225, in _raise_on_error
raise_error(data["error"])
File "/usr/local/lib/python3.10/site-packages/pydeconz/errors.py", line 80, in raise_error
raise pydeconzException(error)
pydeconz.errors.pydeconzException: {'address': '/sensors/27/config/preset', 'description': 'Could not set attribute', 'type': 608}
Edit 2: I tried to set child lock through api (I used curl, because it still doesn't appear in ha). It works!!!
Here my current ddf:
{
"schema": "devcap1.schema.json",
"manufacturername": "$MF_LUMI",
"modelid": "lumi.airrtc.agl001",
"vendor": "Aqara",
"product": "E1 Thermostat",
"sleeper": false,
"status": "Gold",
"path": "/devices/e1_thermostat.json",
"subdevices": [
{
"type": "$TYPE_THERMOSTAT",
"restapi": "/sensors",
"uuid": [
"$address.ext",
"0x01",
"0x0201"
],
"fingerprint": {
"profile": "0x0104",
"device": "0x0301",
"endpoint": "0x01",
"in": [
"0x0000",
"0xfcc0",
"0x0201"
]
},
"items": [
{
"name": "attr/id"
},
{
"name": "attr/lastannounced"
},
{
"name": "attr/lastseen"
},
{
"name": "attr/manufacturername"
},
{
"name": "attr/modelid"
},
{
"name": "attr/name"
},
{
"name": "attr/swversion"
},
{
"name": "attr/type"
},
{
"name": "attr/uniqueid"
},
{
"name": "config/battery",
"read": {
"at": "0x040a",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x040a",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
"default": 0
},
{
"name": "config/heatsetpoint",
"read": {
"at": "0x0012",
"cl": "0x0201",
"ep": 1,
"fn": "zcl"
},
"parse": {
"at": "0x0012",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
},
{
"name": "config/locked",
"read": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0277",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
},
"write": {
"at": "0x0277",
"cl": "0xfcc0",
"dt": "0x20",
"ep": 1,
"eval": "if (Item.val == true) { 1 } else { 0 }",
"fn": "zcl",
"mf": "0x115f"
},
"default": false
},
{
"name": "config/offset",
"default": 0
},
{
"name": "config/on"
},
{
"name": "config/mode",
"read": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = ['off', 'heat'][Attr.val];",
"fn": "zcl",
"mf": "0x115f"
},
"write": {
"at": "0x0271",
"cl": "0xfcc0",
"dt": "0x20",
"ep": 1,
"eval": "if (Item.val == 'off') { 0 } else if (Item.val == 'heat') { 1 }",
"fn": "zcl",
"mf": "0x115f"
}
},
{
"name": "config/preset",
"read": {
"at": "0x0272",
"cl": "0xfcc0",
"ep": 1,
"fn": "zcl",
"mf": "0x115f"
},
"parse": {
"at": "0x0272",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = ['manual', 'auto', 'holiday'][Attr.val];",
"fn": "zcl",
"mf": "0x115f"
},
"write": {
"at": "0x0272",
"cl": "0xfcc0",
"dt": "0x20",
"ep": 1,
"eval": "if (Item.val == 'manual') { 0 } else if (Item.val == 'auto') { 1 } else if (Item.val == 'holiday') { 2 }",
"fn": "zcl",
"mf": "0x115f"
}
},
{
"name": "config/reachable"
},
{
"name": "state/lastupdated"
},
{
"name": "state/on",
"refresh.interval": 5,
"parse": {
"at": "0x0271",
"cl": "0xfcc0",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl",
"mf": "0x115f"
}
},
{
"name": "state/temperature",
"read": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"fn": "zcl"
},
"parse": {
"at": "0x0000",
"cl": "0x0201",
"ep": 1,
"eval": "Item.val = Attr.val;",
"fn": "zcl"
},
"default": 0
}
]
}
],
"bindings": [
{
"bind": "unicast",
"src.ep": 1,
"cl": "0x0201",
"report": [
{
"at": "0x0012",
"dt": "0x29",
"min": 1,
"max": 600
},
{
"at": "0x0000",
"dt": "0x29",
"min": 20,
"max": 300
}
]
}
]
}
Presently I have 6 Eurotronic Radiator valves which work perfect. However, many thermostat radiator valve are presently not available any more for Zigbee. I needed a new valve and bought this Aqara thermostat E1 valve, Solid design and works presently manually.
Device is connected, however not show in the menu and Domoticz does not see the device as well.
Manufacturer Name LUMI Model Identifier lumi.airrtc.agl001
Looks almost identical as the Essentials 120112 Smart Home radiator thermostat.
Device
Screenshots
Basic
Identify
Alarms
Device Temperature
Groups
Scenes
On/Off
Level Control
Color Control
Simple Metering
Diagnostics
Other clusters that are not mentioned above