zigbee2mqtt icon indicating copy to clipboard operation
zigbee2mqtt copied to clipboard

[New device support]: Aqara Smart Radiator Thermostat E1 (SRTS-A01)

Open ccorderor opened this issue 2 years ago • 122 comments

Link

https://www.aqara.com/eu/product/radiator-thermostat-e1

Database entry

{"id":80,"type":"EndDevice","ieeeAddr":"0x54ef441000128356","nwkAddr":12635,"manufId":4447,"manufName":"LUMI","powerSource":"Battery","modelId":"lumi.airrtc.agl001","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":769,"inClusterList":[0,1,3,64704,10,513],"outClusterList":[3,64704,513],"clusters":{"genBasic":{"attributes":{"appVersion":23,"modelId":"lumi.airrtc.agl001"}},"aqaraOpple":{"attributes":{"247":{"type":"Buffer","data":[3,40,30,5,33,1,0,10,33,75,16,13,35,23,8,0,0,17,35,1,0,0,0,101,32,0,102,41,250,10,103,41,140,10,104,35,0,0,0,0,105,32,100,106,32,0]},"625":1,"626":0,"627":0,"628":1,"629":0,"630":{"type":"Buffer","data":[4,62,1,224,0,0,9,96,4,56,0,0,6,164,5,100,0,0,8,152,129,224,0,0,8,152]},"631":0,"633":500,"634":0,"635":1,"636":0,"637":0,"638":0,"640":0,"1034":100}},"hvacThermostat":{"attributes":{"localTemp":2810,"occupiedHeatingSetpoint":2700}},"genPowerCfg":{"attributes":{"batteryVoltage":33}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":23,"hwVersion":1,"dateCode":"Apr 25 2022","swBuildId":"0.0.0_0023","zclVersion":3,"interviewCompleted":true,"meta":{"configured":1906590817},"lastSeen":1663048175699,"defaultSendRequestWhen":"immediate"}

Comments

The device is unsupported. I've created a basic external converter and am able to manually control the heating setpoint, but there are still many custom aqaraOpple messages to be implemented.

For the moment, I'm sure the aqaraOpple message with key id 626 is the antifreeze option (value 2 is on, value 0 is off) aqaraOpple message with key id 625 is manually setting off the TRV (0 is off, 1 is on)

External converter

const definition = {
    zigbeeModel: ['lumi.airrtc.agl001'], // The model ID from: Device with modelID 'lumi.sens' is not supported.
    model: 'SRTS-A01', // Vendor model number, look on the device for a model number
    vendor: 'Xiaomi', // Vendor of the device (only used for documentation and startup logging)
    description: 'Aqara Smart Radiator Thermostat E1', // Description of the device, copy from vendor site. (only used for documentation and startup logging)
    fromZigbee: [fz.thermostat, fz.aqara_opple, fz.battery],
    toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_control_sequence_of_operation,
            tz.thermostat_system_mode, tz.thermostat_keypad_lockout, tz.thermostat_occupied_heating_setpoint], // Should be empty, unless device can be controlled (e.g. lights, switches).
    exposes: [e.battery_voltage(), exposes.climate()
            .withSetpoint('occupied_heating_setpoint', 5, 30, 0.5, ea.STATE_SET).withLocalTemperature(ea.STATE)
            .withSystemMode(['off', 'auto', 'heat'], ea.STATE_SET)
            .withRunningState(['idle', 'heat'], ea.STATE)], // Defines what this device exposes, used for e.g. Home Assistant discovery and in the frontend
    configure: async (device, coordinatorEndpoint, logger) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read('genPowerCfg', ['batteryVoltage']);
        },
};

Supported color modes

No response

Color temperature range

No response

ccorderor avatar Sep 13 '22 05:09 ccorderor

I have already added thermostat converters, but they are not complete. you can add/correct them as needed.

kirovilya avatar Sep 13 '22 06:09 kirovilya

I have already added thermostat converters, but they are not complete. you can add/correct them as needed.

Nice work! I'll check it to see if you have already added the antifreeze and manual option.

Thanks :)

ccorderor avatar Sep 13 '22 06:09 ccorderor

I am named them 'away_preset_temperature' and 'preset'

kirovilya avatar Sep 13 '22 06:09 kirovilya

According to the product page, this thermostat can be linked to an external temperature sensor in the Aqara app. Is it possible to support this as well or is this allegedly based on some proprietary Aqara implementation?

ste-fle avatar Sep 13 '22 08:09 ste-fle

Yes, there is such a possibility. The TH-sensor sends temperature data to the hub, and then the hub sends a control command to the thermostat. Only the command and data are proprietary :) Example: aa:71:13:44:04:8a:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:23:80:00 image

kirovilya avatar Sep 13 '22 08:09 kirovilya

Thanks! Could you explain this part a little further: Only the command and data are proprietary :) Does this mean it's theoretically possible to link to a sensor but in reality due to proprietary commands it's not?

ste-fle avatar Sep 13 '22 09:09 ste-fle

I think if understand the data format, then we can use other sensors. This is not quite a link - this is some kind of external control based on data from the sensor.

kirovilya avatar Sep 13 '22 10:09 kirovilya

I propose to think about how to parse the commands that the gateway sends to the thermostat: their structure and meaning.

send command "link sensor"
aa:71:31:44:00:70:02:41:2e:63:14:57:81:3d:04:54:ef:44:10:00:51:c6:68:00:15:8d:00:01:e4:21:8a:00:01:00:55:13:0a:02:00:00:64:04:ce:c2:b6:c8:00:00:00:00:00:01:3d:64:65
aa:71:34:44:01:6c:02:41:31:63:14:57:81:3d:05:54:ef:44:10:00:51:c6:68:00:15:8d:00:01:e4:21:8a:08:00:07:fd:16:0a:02:0a:c9:e8:b1:b8:d4:da:cf:df:c0:eb:00:00:00:00:00:01:3d:04:65
received 26.09* from TH sensor then send control
aa:71:13:44:02:8c:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:23:10:00
aa:71:13:44:03:8b:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:23:10:00
received 26.16* then send control
aa:71:13:44:04:8a:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:23:80:00
aa:71:13:44:05:89:05:41:10:00:15:8d:00:01:e4:21:8a:08:00:07:fd:00:00:00:01 - ?
received 26.68* then send control 
aa:71:13:44:06:88:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:26:c0:00
received 26.71*  then send control
aa:71:13:44:07:87:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:26:f0:00
received 27.24* then send control
aa:71:13:44:08:86:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:2a:40:00
send command "unlink sensor"
aa:71:1d:44:09:7b:04:41:1a:63:14:59:1d:3d:05:54:ef:44:10:00:51:c6:68:00:00:00:00:00:00:00:00:00:00:00:00

Partially I managed to understand the composition of the package. For example:

aa:71:13:44:02:8c:05:41:10:00:15:8d:00:01:e4:21:8a:00:01:00:55:45:23:10:00

aa:71:13:44: - ? 02: - subsequence 8c: - backwards subsequence 05: - ? command ? 41: - type octetStr 10: - length 16 00:15:8d:00:01:e4:21:8a:00:01:00:55:45:23:10:00 - ?

aa:71:31:44:00:70:02:41:2e:63:14:57:81:3d:04:54:ef:44:10:00:51:c6:68:00:15:8d:00:01:e4:21:8a:00:01:00:55:13:0a:02:00:00:64:04:ce:c2:b6:c8:00:00:00:00:00:01:3d:64:65

aa:71:31:44: - ? 00: - subsequence 70: - backwards subsequence 02: - ? command ? 41: - type octetStr 2e: - length 46 63:14:57:81:3d:04:54:ef:44:10:00:51:c6:68:00:15:8d:00:01:e4:21:8a:00:01:00:55:13:0a:02:00:00:64:04:ce:c2:b6:c8:00:00:00:00:00:01:3d:64:65 - ? here the second octetStr also has a familiar value - ieee temperature sensor address 54:ef:44:10:00:51:c6:68:

kirovilya avatar Sep 13 '22 17:09 kirovilya

Thank you @kirovilya for your contribution! I'm using the thermostat with the latest dev branch. Please excuse my question. Do we know if local_temperature really corresponds to the measured temperature the thermostat uses to adjust the valve or rather the internal SoC temperature or something else? I'm asking because my reading is far off from other temp sensors in the room, knowing full well that the value at the radiator can of course differ, but for me the value makes no sense. After all, my device could also be broken :D

Edit: My first device actually had a defective temperature sensor.

0ip avatar Sep 13 '22 20:09 0ip

@0ip as far as I understand, these are the readings of the internal temperature sensor, according to which the thermostat is adjusted

kirovilya avatar Sep 14 '22 05:09 kirovilya

Just checking in to request this device be added. I'm happy to help test things - how do I switch my HA addon installation to the dev branch without losing all my existing devices/config? cheers

trullock avatar Sep 20 '22 10:09 trullock

Any news on this? I just received and installed my thermostat as well, so I'd also help if possible/necessary.

ste-fle avatar Sep 24 '22 14:09 ste-fle

Thanks for your work. Currently turning the device on or off from Home Assistant does not actually turn on or off the thermostat in Z2M. But it works fine from Z2M.

lunatik98 avatar Sep 27 '22 09:09 lunatik98

Just checking in to request this device be added. I'm happy to help test things - how do I switch my HA addon installation to the dev branch without losing all my existing devices/config? cheers

Just stop the normal Z2M, copy the settings from the addon to the dev version and start it :)

lunatik98 avatar Sep 27 '22 09:09 lunatik98

One issue I've found is that when you change the set point to either above or below the current temperature, and you hear the physical valve open/close, the valve state switch doesn't update, meaning you cant know if its open or not (without making an assumption from the temperature difference)

trullock avatar Oct 01 '22 22:10 trullock

[aa:71]:[13]:44:2b:63:05:41:10:[00:15:8d:00:04:44:c8:24]:00:01:00:55:[45:19:60:00]
[aa:71]                               : const
[13]                                    : data offset
[00:15:8d:00:04:44:c8:24] : zbee_nwk.src64(temperature sensor) [45:19:60:00]                     : temperature (type float)

artem-sedykh avatar Oct 03 '22 11:10 artem-sedykh

Not sure if this is useful, here's an unhandled message (247/0xf7) that I receive

 2022-10-03 20:30:42Received Zigbee message from 'Radiator', type 'attributeReport', cluster 'aqaraOpple', data '{"247":{"data":[3,40,21,5,33,1,0,10,33,21,178,13,35,25,8,0,0,17,35,1,0,0,0,101,32,0,102,41,108,7,103,41,96,9,104,35,0,0,0,0,105,32,100,106,32,0],"type":"Buffer"}}' from endpoint 1 with groupID 0

trullock avatar Oct 03 '22 19:10 trullock

send command "link sensor"

const data offset const subsequence backwards subsequence command const data length data block
aa:71 31 44 63 0d 02 41 2e
constrnd?constdevice addresssensor addressconstconst
633b:38:fd3d:0454:ef:44:10:00:51:cf:e600:15:8d:00:04:44:c8:2400:01:00:5513:0a:02:00:00:64:04:ce:c2:b6:c8:00:00:00:00:00:01:3d:64:65
aa:71 34 44 64 09 02 41 31
constrnd?constdevice addresssensor addressconstconst
633b:38:fd3d:0554:ef:44:10:00:51:cf:e600:15:8d:00:04:44:c8:2408:00:07:fd16:0a:02:0a:c9:e8:b1:b8:d4:da:cf:df:c0:eb:00:00:00:00:00:01:3d:04:65
aa:71 12 44 65 29 05 41 10
sensor addressconsttemperature(float)
00:15:8d:00:04:44:c8:2400:01:00:5545:1a:b0:00

artem-sedykh avatar Oct 03 '22 20:10 artem-sedykh

Header

The header for all commands on 0xfff2 is described here: https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Aqara-S1-Smart-Scene-Panel-Protocol#general-commands-structure

Command Start Command category CMD Size CMD Type Counter Integrity CMD Action Data Type Params Size
aa 71 31 44 10 60 02 41 2e

I wrote a quick implementation of this:

const aqaraHeader = (counter, params, action) => {
    // Based on https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Aqara-S1-Smart-Scene-Panel-Protocol
    const header = [
        0xaa, // static
        0x71, // to device
        params.length + 3, // CMD Size (all params after integrity)
        0x44, // CMD Type
        counter, // Counter
    ];
    const integrity = 512 - header.reduce((sum, elem) => sum + elem, 0);
    return [
        ...header,
        integrity,
        action, // 0x02 for linking sensor, 0x04 for unlinking, 0x05 when setting temperature state
        0x41, // Octet string
        params.length, // Params size
    ];
};

Some more details about "link sensor":

Linking consists of two commands which are always sent in the same order. I'm not sure if both are required but at least one of them has to be sent before setting temperature state. The first 4 hex codes are unix timestamp in seconds encoded as int. E.g. 0x6339bf17 => 1664728855 => Sun Oct 2 06:40:55 PM CEST 2022.

Link 1:

Timestamp Const Link 1 Device address Sensor address Const shared between first link and write temp state Const for link 1 Common between links Const link 1 End
63:39:bf:0e 3d 04 54:ef:44:10:00:51:c2:5a 00:15:8d:00:07:f8:06:22 00:01:00:55 13:0a:02:00:00:64:04:ce:c2:b6:c8 00:00:00:00:00:01:3d 64 65

Link 2:

Timestamp Const Link 2 Device address Sensor address Const for link 2 Common between links Link 1(?) End
63:39:bf:0e 3d 05 54:ef:44:10:00:51:c2:5a 00:00:00:00:00:00:00:00:00:00:00:00 08:00:07:fd:16:0a:02:0a:c9:e8:b1:b8:d4:da:cf:df:c0:eb 00:00:00:00:00:01:3d 04 65

Set external sensor temp

While reverse engineering the temperature I didn't realize that the value was encoded as float so I accidentally wrote a shitty implementation of floating point. Glad that never has to see the light of day. :smile: Instead we can just use this:

const value = 23.57;
const temperatureBuf = Buffer.allocUnsafe(4);
temperatureBuf.writeFloatBE(Math.round(value * 100));

temperatureBuf: <Buffer 45 13 50 00> As a side note I find it weird that they use floating point instead of int here since they don't even use the fraction part.

When an external sensor temperature is set the TRV reports LocalTemperature with the specified temperature so it doesn't look like we have to any special handling here compared to using the internal sensor.

Unlinking (going back to internal sensor):

Looks like this time the commands are sent in opposite order (05 then 04).

Timestamp Const Link 2 Device address Const
63:39:bf:0e 3d 05 54:ef:44:10:00:51:c2:5a 00:00:00:00:00:00:00:00:00:00:00:00
Timestamp Const Link 1 Device address Const
63:39:bf:0e 3d 04 54:ef:44:10:00:51:c2:5a 00:00:00:00:00:00:00:00:00:00:00:00

Sending temperature in zigbee2mqtt

const params = [
  ...sensor,
  0x00, 0x01, 0x00, 0x55, // static?
  ...temperatureBuf,
];
const value = [
  ...(aqaraHeader(0x12, params, 0x05)),
  ...params,
];

await entity.write('aqaraOpple', {0xfff2: {value, type: 0x41}}, 0x115f);

I'm not sure if the sensor address actually matters but the same address has to be used when linking and when setting temperature. Likely we can get away with using a static address. I'm also not sure if increasing the counter actually makes a difference as just using the same value does seemingly work. Might make a difference if commands are sent rapidly?

duvholt avatar Oct 04 '22 10:10 duvholt

One issue I've found is that when you change the set point to either above or below the current temperature, and you hear the physical valve open/close, the valve state switch doesn't update, meaning you cant know if its open or not (without making an assumption from the temperature difference)

May I ask which topic in MQTT you are using to check if the valve is open or closed? I don't seem to find this feature. I can only find the switch "Valve_detection", but I guess this is to enable/disable the feature of reading the valve state.

Is this generally supported by the device, to see valve state?

nickagian avatar Oct 04 '22 16:10 nickagian

One issue I've found is that when you change the set point to either above or below the current temperature, and you hear the physical valve open/close, the valve state switch doesn't update, meaning you cant know if its open or not (without making an assumption from the temperature difference)

May I ask which topic in MQTT you are using to check if the valve is open or closed? I don't seem to find this feature. I can only find the switch "Valve_detection", but I guess this is to enable/disable the feature of reading the valve state.

Is this generally supported by the device, to see valve state?

I'm not sure if this is a feature, but I'd expect it to be. I'm expecting the on/off switch to have its state updated if the valve determines it should be on/off automatically or through physical adjustment of the device. Is this not the case?

Valve Detection seems to be a badly named feature, and is really something else:

You can enable/disable the Valve Detection function on the settings page. In order to prevent the prolonged low-temperature or high-temperature state of room temperature from becoming uncomfortable, the thermostat will remind the user of temperature control abnormality when it detects that the room temperature can’t reach the set temperature, after heating is started, for the following possible causes: The thermostat is not installed correctly. It is suggested that you should remove the battery and put it back 30 sec later, then reinstall the thermostat and calibrate it again, and further wait for a period of time, and then observe whether the fault is eliminated. The room temperature is significantly higher than the set temperature due to the incorrect temperature setting. It is suggested that you should re-set the temperature again, wait for a period of time, and then observe whether the fault is eliminated. Valve failure. Please replace the valve, reinstall the thermostat, and carry out valve calibration. The room is too large (the radiator is not matching) or there is too much ventilation in the room. It is suggested that you should replace the radiator or test whether the room door or window is opened or leaking air. The inlet water pressure or inlet water temperature is too low. Please check the inlet water pressure and inlet water temperature. Upon networking with the temperature sensors, no linkage is established with the temperature sensor in the same room, or the distance from the temperature sensor to the radiator is remote (it is recommended that the temperature sensor should be placed in the same room with the thermostat, for a distance of 2-3m from the thermostat).

It might be helpful to either alude to this in the UI or otherwise completely rename it to something sensible

trullock avatar Oct 04 '22 21:10 trullock

Valve Detection seems to be a badly named feature, and is really something else:

You can enable/disable the Valve Detection function on the settings page. In order to prevent the prolonged low-temperature or high-temperature state of room temperature from becoming uncomfortable, the thermostat will remind the user of temperature control abnormality when it detects that the room temperature can’t reach the set temperature, after heating is started, for the following possible causes:

The thermostat is not installed correctly. It is suggested that you should remove the battery and put it back 30 sec later, then reinstall the thermostat and calibrate it again, and further wait for a period of time, and then observe whether the fault is eliminated.

The room temperature is significantly higher than the set temperature due to the incorrect temperature setting. It is suggested that you should re-set the temperature again, wait for a period of time, and then observe whether the fault is eliminated.

Valve failure. Please replace the valve, reinstall the thermostat, and carry out valve calibration.

The room is too large (the radiator is not matching) or there is too much ventilation in the room. It is suggested that you should replace the radiator or test whether the room door or window is opened or leaking air.

The inlet water pressure or inlet water temperature is too low. Please check the inlet water pressure and inlet water temperature.

Upon networking with the temperature sensors, no linkage is established with the temperature sensor in the same room, or the distance from the temperature sensor to the radiator is remote (it is recommended that the temperature sensor should be placed in the same room with the thermostat, for a distance of 2-3m from the thermostat).

It might be helpful to either alude to this in the UI or otherwise completely rename it to something sensible

This function can show an icon on the thermostat screen in case one of the conditions above fires. The manual refers to this as "fault icon". So maybe this function / switch should rather be called something like "fault detection" in combination with further documentation (e.g. the conditions above) and that this enables this icon on the screen.

ste-fle avatar Oct 05 '22 08:10 ste-fle

This function can show an icon on the thermostat screen in case one of the conditions above fires. The manual refers to this as "fault icon". So maybe this function / switch should rather be called something like "fault detection" in combination with further documentation (e.g. the conditions above) and that this enables this icon on the screen.

I think if anything is done here it should be additive, e.g. call it "Fault (Valve) Detection", as renaming it alone creates a mismatch between feature names which is arguably more confusing - Whos to know theyre the same feature and not different features?

trullock avatar Oct 05 '22 10:10 trullock

One issue I've found is that when you change the set point to either above or below the current temperature, and you hear the physical valve open/close, the valve state switch doesn't update, meaning you cant know if its open or not (without making an assumption from the temperature difference)

May I ask which topic in MQTT you are using to check if the valve is open or closed? I don't seem to find this feature. I can only find the switch "Valve_detection", but I guess this is to enable/disable the feature of reading the valve state. Is this generally supported by the device, to see valve state?

I'm not sure if this is a feature, but I'd expect it to be. I'm expecting the on/off switch to have its state updated if the valve determines it should be on/off automatically or through physical adjustment of the device. Is this not the case?

Valve Detection seems to be a badly named feature, and is really something else:

You can enable/disable the Valve Detection function on the settings page. In order to prevent the prolonged low-temperature or high-temperature state of room temperature from becoming uncomfortable, the thermostat will remind the user of temperature control abnormality when it detects that the room temperature can’t reach the set temperature, after heating is started, for the following possible causes: The thermostat is not installed correctly. It is suggested that you should remove the battery and put it back 30 sec later, then reinstall the thermostat and calibrate it again, and further wait for a period of time, and then observe whether the fault is eliminated. The room temperature is significantly higher than the set temperature due to the incorrect temperature setting. It is suggested that you should re-set the temperature again, wait for a period of time, and then observe whether the fault is eliminated. Valve failure. Please replace the valve, reinstall the thermostat, and carry out valve calibration. The room is too large (the radiator is not matching) or there is too much ventilation in the room. It is suggested that you should replace the radiator or test whether the room door or window is opened or leaking air. The inlet water pressure or inlet water temperature is too low. Please check the inlet water pressure and inlet water temperature. Upon networking with the temperature sensors, no linkage is established with the temperature sensor in the same room, or the distance from the temperature sensor to the radiator is remote (it is recommended that the temperature sensor should be placed in the same room with the thermostat, for a distance of 2-3m from the thermostat).

It might be helpful to either alude to this in the UI or otherwise completely rename it to something sensible

I definitely agree with you. Something like is expected to be present from a smart thermostat, otherwise how can you monitor when it is operating or not?

nickagian avatar Oct 05 '22 16:10 nickagian

image

artem-sedykh avatar Oct 09 '22 09:10 artem-sedykh

Now that we know how the linking procedure to an external temperature sensor works, thanks to @duvholt and others, should/can it be integrated into Z2M, or should that be left to applications built on top of Z2M?

0ip avatar Oct 09 '22 12:10 0ip

@0ip I would say that Z2M should expose this feature through MQTT topics. Isn't that common practice?

nickagian avatar Oct 09 '22 12:10 nickagian

I have this TRV only reporting local_temperature at steps of 1.0 degree as 18.2, 19.2, 20.2 etc. Is this normal?

gdschut avatar Oct 09 '22 13:10 gdschut

Now that we know how the linking procedure to an external temperature sensor works, thanks to @duvholt and others, should/can it be integrated into Z2M, or should that be left to applications built on top of Z2M?

I added the ability to switch to an external and internal temperature sensor, as well as sending temperature from an external sensor PR

artem-sedykh avatar Oct 09 '22 14:10 artem-sedykh