Issue with single precision not converting (analog output / present value)

Hello. I just got a set of Xiaomi curtains working using a switch device handler, and wanted to see if I could update the open/close status when the curtains are open manually.

When they are opened or closed, they send a read attribute message. Cluster is 000D (analog output (basic)), and attribute id is 0055 (present value). Per the spec, the value should be a single precision floating point value.

However, that should come as a 32bit binary value or a 8bit hex value, I believe. Instead, I’m getting a 22bit hex value, like this: 0339c00023f00042b40000.

If anyone could point me in the right direction, I’d appreciate the help.

Xiaomi doesn’t necessarily follow strict Zigbee protocol for it’s messages. So I wouldn’t automatically believe that a message coming from cluster 000D attribute 0055 is following the Zigbee specification.

Also, think about actual use in terms of the product. Why send an analog value? From what I’ve read, this motor is self-adjusting. After pairing, the first time it is closed it will auto-sense the curtain rail length. So all that’s needed in terms of message sent to the hub is a “I’m closed now” or “I’m open now” kind of message.

The only reason I can think of that an analog value would be needed is to send an exact rail position, but that doesn’t make a lot of sense.

There’s only one way to find out, which is to somehow try testing the auto-sense feature with different rail lengths and see if the messages sent at open/close are different. For that matter, are the messages consistent on open/close now, or are they a little different each time?

Most importantly, it would be helpful to post the entire debug log output of the message received.

I wondered why it was an analog value, but I figured it might make sense once I got it converted to decimal. What you’re saying makes sense. Either rail position, or simply # of rotations, if they don’t assume a certain gear ratio in the rail. When I get home I can post more details, but no, the values are not perfectly consistent. I think the only thing that I’ve seen stay the same every time is the 23f0 in the middle, and possibly some 0’s on either side of that. Also, yes, it does auto sense the length of the rail the first time it runs.

I noticed this screenshot on the AliExpress page for the Curtain Motor:

So it seems there is exact position control functionality.

Just trust me when I say that Xiaomi doesn’t always format attribute messages as they are documented by the Zigbee Alliance. So some reverse-engineering will be required.

The tricky thing will be figuring out how the value relates to the full closed position. It could be a relative or absolute value, and that would only come out through testing with different rail lengths. It might be possible to simulate different rail lengths by artificially stopping the curtain/motor after pairing it.

Turns out I can add the images from iCloud Drive. Is there anything in the log messages that I personally identifying and not safe to post?

Also, any idea on how to convert these values to something in base 10 that we can recognize? Will probably help with figuring out the length question. You’ve probably seen this, but you can tug the curtain to tell it to open or close. The curtain typically sides 2-3 inches before the motor catches and starts pulling.

Nothing to worry about there. If possible, it would help to copy the actual text and paste it inside the pre-formatted (code) tags, which is a set of two of these ` to get text displayed like this:

12:55:00 PM: debug description is read attr - raw: 70A70107020C00042A000000, dni: 70A7, endpoint: 01, cluster: 0702, size: 0C, attrId: 0400, encoding: 2A, value: 000000

(I removed the preceding hex device identifier).

Anyhow, before converting any values, we need to figure out which values change when something happens and which ones can be ignored.

The SmartThings Zigbee parser reverses the order of pairs of bytes in what’s listed for the value as compared to the raw hex output, probably under the assumption they are 16-bit values that need big-endian changed to little-endian. I’ll set that aside for now, and just look at the relevant portion of the raw hex string (after removing the dni, endpoint, cluster, etc.). Big vs Little endian to get correct values can be looked at later.

I assume there’s a few seconds between the time the motor kicks in and when it’s finished opening / closing, so here’s what I’m seeing:

Open by hand - both attempts
00 00 10 41 00 F0 23 00 C0 39 03 (motor starts opening)
then
00 00 C8 42 00 F0 23 00 00 00 00 (finished opening)

Close by hand - first attempt
00 00 B4 42 00 F0 23 00 C0 39 03 (motor starts closing)
then
00 00 00 00 00 F0 23 00 00 00 00 (finished closing)

Close by hand - second attempt
00 00 BC 42 00 F0 23 00 C0 39 03 (motor starts closing)
then
00 00 00 00 00 F0 23 00 00 00 00 (finished closing)

There’s not a whole lot to go on yet, but my guesses are this:

  • F0 23 can be safely ignored, and may be a second embedded attribute Id (not normal for the Zigbee spec, but I’ve see other Xiaomi devices do this).
  • 00 C0 39 03 likely has to do with the motor turning on (or perhaps being manually turned on), but nothing to do with the direction because the value is the same both for opening and closing.
  • Bytes 4 and 5 probably relate to the position and / or direction of curtain travel. I would go further to say that for byte 5, 41 likely represents full closed and 42 full open. So then byte 4 would likely be an 8-bit value used for the exact position. If true, then the “calibration” routine of setting rail length the first time the curtain is closed after the motor is paired would set full closed to 00 and full open would be a value relative to FF being the widest curtain rail length possible. What throws me off is that the message sent after the motor is finished closing is all 00 except for the f0 23.

Or… I could be totally wrong. Seeing log output that happens when the SmartThings app is used to switch on the motor would help.

I do know the biggest challenge will be to figure out the format of the command to open / close to a certain position.

I will try to get actual text tonight. I just took screenshots last night when I was looking at it and then printed and started comparing what changed and what didn’t.

I assume it will be best to get two events for each combination of: open, close, manual, app. Right?

Two other thoughts. It may be that closed is 0, instead of open being 0. Or, worst case, it varies depending on which direction it moves first on starting up. Also, I would bet against relative. There is no theoretical limit to the length, as the motor just turns. If I knew how to reliably reset it, I could test this by taking it off the rail, resetting it, telling it to start and then let it run for a minute or two straight. My guess is that, with no resistance to trigger “closed”, it will just run indefinitely.

Definitely, because if the position is a little different, then we’d see that particular value change.

Over on the OpenHAB community forums, I read this:

I found out the Curtain item has a event , which will cause the whole binding stop working.

Sometimes the curtain motor will report the value “-1”, i have to reset the curtain myself,

Item got update: {“cmd”:“read_ack”,“model”:“curtain”,“sid”:“158d00012d69e7”,“short_id”:56211,“data”:“{“voltage”:3600,“curtain_level”:”-1"}"}

Though the value range is 0-100, but sometimes when the curtain motor stuck, it will send -1

the -1 will crash the whole binding.

The OpenHAB connects to Xiaomi devices by interfacing with a Xiaomi hub that’s been put into developer mode, so it’s quite different from SmartThings, which connects directly with the devices via Zigbee. Nevertheless from this user report it seems that motor voltage may be something that’s reported in addition to the “level” (which I assume is the same as what I’m calling “position”.)

When they say “binding” it’s about the way OpenHAB binds to their driver to handle Xiaomi messages. So nothing to worry about there. But knowing about the -1 level reported when the motor gets stuck will be helpful to know, once we’ve seen how that’s represented in an 8-bit (or 16-bit) value.

Perhaps, but there has to be some way to translate a percentage open to a relative value. I assume that the position isn’t based on time of the motor running, because that isn’t reliable enough with variations in voltage, weight slowing things down, etc. So it’s probably based on revolutions of a gear set. Even if that is represented with a 16-bit value, it still would have a limit. And then the range of 1-100% needs to be relative to full open and full closed. That relative value range is either calculated and stored in the hardware, or it’s derived in the Xiaomi app. My hope is that it’s stored in the hardware, based on the initial calibration, which would make things a lot easier in coding the device handler.

Didn’t have time to clean these up, but hopefully this is what you were after?
Let me know what else I can do or look into.

App open

4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:52 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:52 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:52 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00042c80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:43 PM: debug Parse returned [name:switch, value:on, isStateChange:false, displayed:false, linkText:Bedroom Curtains, descriptionText:Bedroom Curtains switch is on] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:43 PM: debug [name:switch, value:on, type:switch] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:43 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:43 PM: debug Parsing 'on/off: 1' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug SmartShield(clusterId: 0x0006, command: 0x0b, data: [0x01, 0x00], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: false, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x39c0, sourceEndpoint: 0x01, text: null) 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug Parsing 'catchall: 0104 0006 01 01 0100 00 39C0 00 00 0000 0B 01 0100' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:53:42 PM: debug on()

App close
4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:55:00 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:55:00 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:55:00 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:58 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:58 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:58 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000A04200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042a00000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042c80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:50 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:50 PM: debug SmartShield(clusterId: 0x0006, command: 0x0b, data: [0x00, 0x00], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: false, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x39c0, sourceEndpoint: 0x01, text: null) 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:50 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:50 PM: debug Parsing 'catchall: 0104 0006 01 01 0100 00 39C0 00 00 0000 0B 01 0000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug Parse returned [name:switch, value:off, isStateChange:false, displayed:false, linkText:Bedroom Curtains, descriptionText:Bedroom Curtains switch is off] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug [name:switch, value:off, type:switch] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:51 PM: debug Parsing 'on/off: 0' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:54:50 PM: debug off()

App open 2
4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:43 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:43 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:43 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00042c80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:43 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:43 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:43 PM: debug Parsing 'read attr - raw: 39C001000D1C55003900003C4200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f000423c0000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parse returned [name:switch, value:on, isStateChange:false, displayed:false, linkText:Bedroom Curtains, descriptionText:Bedroom Curtains switch is on] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug [name:switch, value:on, type:switch] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parsing 'on/off: 1' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:34 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:33 PM: debug on() 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:33 PM: debug on() 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:33 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:33 PM: debug SmartShield(clusterId: 0x0006, command: 0x0b, data: [0x01, 0x00], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: false, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x39c0, sourceEndpoint: 0x01, text: null) 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:33 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:56:33 PM: debug Parsing 'catchall: 0104 0006 01 01 0100 00 39C0 00 00 0000 0B 01 0100'

App close 2
4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:23 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:23 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:23 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:23 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:23 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:23 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000444200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042440000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042c80000' 12:57:14 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042c80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug Parse returned [name:switch, value:off, isStateChange:false, displayed:false, linkText:Bedroom Curtains, descriptionText:Bedroom Curtains switch is off] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug [name:switch, value:off, type:switch] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:14 PM: debug Parsing 'on/off: 0' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:13 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:13 PM: debug SmartShield(clusterId: 0x0006, command: 0x0b, data: [0x00, 0x00], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: false, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x39c0, sourceEndpoint: 0x01, text: null) 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:13 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:13 PM: debug Parsing 'catchall: 0104 0006 01 01 0100 00 39C0 00 00 0000 0B 01 0000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:13 PM: debug off() 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:57:13 PM: debug off()

Manual open
4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:13 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:13 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:13 PM: debug Parsing 'read attr - raw: 39C001000D1C55003900000C4200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f000420c0000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:13 PM: debug Parsing 'read attr - raw: 39C001000D1C55003900000C4200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f000420c0000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:06 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:06 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:06 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000604100F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00041600000'

Manual close

4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:47 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:47 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:47 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:47 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:47 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000000000F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00000000000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug SmartShield(clusterId: 0x0000, command: 0x0a, data: [0x01, 0xff, 0x42, 0x1c, 0x03, 0x28, 0x21, 0x05, 0x21, 0x13, 0x00, 0x64, 0x20, 0x5b, 0x08, 0x21, 0x09, 0x11, 0x07, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x21, 0x00, 0x01], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: false, isManufacturerSpecific: true, manufacturerId: 0x115f, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x39c0, sourceEndpoint: 0x01, text: null) 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug Parsing 'catchall: 0104 0000 01 01 0100 00 39C0 00 01 115F 0A 01 01FF421C0328210521130064205B082109110727000000000000000009210001' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug Parsing 'catchall: 0104 0000 01 01 0100 00 39C0 00 01 115F 0A 01 01FF421C0328210521130064205B082109110727000000000000000009210001' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:58:39 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000B64200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042b60000'

Manual open 2 - pulled curtain a little further than first time
4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:17 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:17 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:17 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00042c80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:17 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:17 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000C84200F02300000000, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0000000023f00042c80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:11 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:11 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 12:59:11 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000604100F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00041600000'

Manual close 2 - pulled curtain a little further than first time

4723ee59-e6d5-4c20-80f1-868e7b4cf297 1:00:03 PM: debug Parse returned [:] 4723ee59-e6d5-4c20-80f1-868e7b4cf297 1:00:03 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 1:00:03 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000A84200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042a80000' 4723ee59-e6d5-4c20-80f1-868e7b4cf297 1:00:03 PM: debug Parse: null 4723ee59-e6d5-4c20-80f1-868e7b4cf297 1:00:03 PM: debug Parsing 'read attr - raw: 39C001000D1C5500390000A84200F02300C03903, dni: 39C0, endpoint: 01, cluster: 000D, size: 1C, attrId: 0055, encoding: 39, value: 0339c00023f00042a80000'

No worries, and yes it should hopefully help.

I distilled all of that to the most relevant events / data, reordered in top to bottom sequence, and get this:

(click the arrow to reveal)

Open via App - 1

  1. on() command sent
  2. read attr - raw: value: 00 00 00 00 00 F0 23 00 C0 39 03 (twice)
  3. on/off: 1(switch on message received)
    (9 seconds pass)
  4. read attr - raw: value: 00 00 C8 42 00 F0 23 00 00 00 00

Open via App - 2

  1. on() command sent (twice)
  2. read attr - raw: value: 00 00 00 00 00 F0 23 00 C0 39 03
  3. on/off: 1(switch on message received)
  4. read attr - raw: value: 00 00 00 00 00 F0 23 00 C0 39 03
    (9 seconds pass)
  5. read attr - raw: value: 00 00 3C 42 00 F0 23 00 C0 39 03
  6. read attr - raw: value: 00 00 C8 42 00 F0 23 00 00 00 00

Manual Open - 1

  1. read attr - raw: value: 00 00 60 41 00 F0 23 00 C0 39 03
    (7 seconds later)
  2. read attr - raw: value: 00 00 0C 42 00 F0 23 00 C0 39 03 (twice)

Manual Open - 2 (pulled a little further)

  1. read attr - raw: value: 00 00 60 41 00 F0 23 00 C0 39 03
    (6 seconds pass)
  2. read attr - raw: value: 00 00 C8 42 00 F0 23 00 00 00 00

Close via App - 1

  1. off() command sent
  2. on/off: 0(switch off message received)
  3. read attr - raw: value: 00 00 C8 42 00 F0 23 00 C0 39 03
    (7 seconds pass)
  4. read attr - raw: value: 00 00 A0 42 00 F0 23 00 C0 39 03
  5. read attr - raw: value: 00 00 00 00 00 F0 23 00 00 00 00

Close via App - 2

  1. off() command sent (twice)
  2. 'on/off: 0' (switch off message received)
  3. read attr - raw: value: 00 00 C8 42 00 F0 23 00 C0 39 03 (twice)
    (9 seconds pass)
  4. read attr - raw: value: 00 00 44 42 00 F0 23 00 C0 39 03
  5. read attr - raw: value: 00 00 00 00 00 F0 23 00 00 00 00

Manual Close - 1

  1. read attr - raw: value: 00 00 B6 42 00 F0 23 00 C0 39 03
  2. catchall: 0104 0000 01 01 0100 00 39C0 00 01 115F 0A 01 01FF421C0328210521130064205B082109110727000000000000000009210001(twice)
    (8 seconds pass)
  3. read attr - raw: value: 00 00 00 00 00 F0 23 00 00 00 00 (twice)

Manual Close - 2 (pulled a little further)

  1. read attr - raw: value: 00 00 A8 42 00 F0 23 00 C0 39 03
  2. read attr - raw: value: 00 00 A8 42 00 F0 23 00 C0 39 03

NOTE: read attr raw values all received from cluster: 000D, attrId: 0055

Some observations:

  • Some messages were received twice. I’ve seen this with other Xiaomi devices, and it shouldn’t be a major concern.

  • The last four bytes of the read attr raw value appear to indicate the state of the motor: 00 C0 39 03 for moving, and 00 00 00 00 for finished moving. But this is not 100% consistent - there’s no message with a value ending in 00 00 00 00 in Manual Open test #2 and Manual Close test #2.

  • Byte #4 of the read attr raw value is one of three values: 00, 41, or 42. A value of 41 only occurred at the start of a manual open, and it seems that a value of 42 might correspond to an open / partial open state, but it’s not 100% consistent.

  • Byte #3 of the read attr raw value is the only one with a variety of values, and I believe more strongly now that this corresponds to the open / close position. I notice that for 3 of the 4 open tests -AND- at the start of both close-via-app tests, that byte value was C8 when the motor was finished, which is equal to a decimal value of 200. Coincidence? I suspect not. There are some incongruous values, though, for example A0 at the end of close-via-app test #1 and 44 at the end of close-via-app test #2. However, those may just be reporting of the position before the motor had finished fully closing. Are you using the motor fully installed with a curtain/set of curtains?

  • The catchall message looks very much like the one sent by other Xiaomi devices when they send their hourly check-in message to the hub. So I don’t believe that is related to the manual close action at all. If true, it’s in a proprietary format and there’s no information on what data is contained (or event relevant) there.

  • I had a look at the Zigbee Cluster Library Specification documentation to read up on the Analog Output (basic) cluster. Since the Present Value attribute (0055) is supposed to be a single precision floating point as you found, and that should be contained in 4 bytes, I am now quite sure Xiaomi isn’t following the Zigbee specification in their use of that cluster/attribute data.

So far, I don’t see enough consistency in the message output to correlate any of those values to something useful to be used in the device handler. But certainly it can be modified so that all instances of on / off in the GUI of the device handler are relabeled “open” / “close”. It just would be nice to use messages as feedback of when the motor was actually finished opening or closing the curtain as opposed to relying on the on/off: 0 or 1 message that happens at the start of the open / close action.

Thanks for looking into all that data.

Yes

I’ve already changed the label for “on” to “open” and “off” to “closed” in my own version of the device handler. Was that what you were suggesting? If there was a way, I’d like to have it update the status if I open the curtains manually, but I’m assuming that won’t work, since there wasn’t anything that seemed to reliably indicate that.

Is there anything else that I can test that might help us? Byte 3 seemed most interesting from your notes.

An important consideration for the device handler, if others will be using it, is how it integrates with SmartThings. The device handler needs to declare the capabilities of the device to make it available to Smart Apps.

Although the Zigbee messages for the curtain motor work using generic switch commands and attribute reports, the on / off events posted in SmartThings of course won’t match what the device does. But there isn’t any curtain motor capability so the closest capability I can think of is Door Control, which is supported in both the Classic (older) and new ST Mobile Apps. So my suggestion is to re-work the DTH to be based on the Door Control capability (I can help with that).

More data based on actual usage would help. What I could do is set up two levels of logging (“info” and “debug”) in the device handler, and then set up info logging to spit out easier to read reporting of actions, (e.g., “Open command sent”, “Open status message received”) and more importantly hex & decimal output of bytes #3 and #4 for every instance of read attr raw value received. Also log entries of the last 4 bytes. The debug level logging would be more or less the same as what you’re seeing for log output now.

With that “info” level logging turned on and the debug level off, it would be much easier to read through to look for any correlations and see what messages are consistent or not over time.

Ok, that would be great. I wouldn’t mind learning how to create these, but I’m a bit confused about where to start writing one from the ground up. If you can point me in the right direction, or want to hop on a Skype, I’ll be glad to give it a shot, or if it’s easier for you to just code it, that works, too.

Would this be sent to the events list so I can always see it, even without going to the Live Logging screen? Also, do you have to be sitting on that Live Logging screen to see debug messages? Or can you pull up historical messages somehow?

To be honest, I wouldn’t put in a grand effort because with the SmartThings platform transition the Groovy language-based device handlers / smart apps may be a thing of the past fairly soon. My take is it’s easier to modify an existing device handler to suit your needs. In helping to work on improving the other Xiaomi device handlers, I’ve “borrowed” from all kinds of existing sources.

If you have a GitHub account, then we could collaborate on modifying the driver there. I can start by lifting the info / debug logging preference and output code from another Xiaomi DH I’ve worked on recently.

Events aren’t meant to be used as a form of debug logging. It’s part of the way the hub is aware of what’s happening with devices, and giving Smart Apps access to events. I don’t know which platform you use for your main home computer, but what I normally do is leave a Live Logging window open in Chrome over a period of days to collect log output for a device. Filtering just that device’s log output is easy - click on it’s name. There’s no way to store Live Logging output somewhere to review later - that I’m aware of.

Ok, let me know when you’ve got something on GitHub and I’ll pull it down.

I run Macs. I’ll try leaving it open. It usually logs me out of the website after a while. May be due to the computer sleeping though.

I have updated the Aqara Curtain Motor DTH to what should hopefully be a fully working beta.

The updated DTH code can be copied from here, and I’ll be adding comments / changelists on the GitHub Pull Request here.

The most important change was going from using capability switch to Door control, which seems to be the most appropriate device class to assign to a curtain motor device.

Also, the preference settings now include toggles for info and debug message output to Live Logging, and the info messages will include more specific information regarding relevant attribute report messages received from the motor that still need interpreting. The default is for only info logging to be output, which is because that will provide the most useful feedback. debug logging can be used as a fallback to look at whats going on in far more detail.

Change List (click arrow to reveal)

• changed capability Switch to Door control
• changed on/off references to open/close where needed
• added “open” and “close” app buttons which can be used in addition to pressing on the main tile (which works as a toggle)
• added an 8 second countdown timer to update opening / closing status to open / closed, respectively (because a attribute report message that the motor has finished opening / closing hasn’t been confirmed)
• added installed(), configure(), and updated() routines to make sure health check interval is set either when the device is paired or preferences are set. These routines can be expanded later if anything else needs to be set up at the time of pairing or when preferences are saved.
• added user-selectable preferences for “Info” and Debug message logging, along with displayDebugLog() and displayInfoLog() routines.
• renamed lastCheckin custom event sent on every received message to lastCheckinCoRE, which now stores an Epoch Date/Time stamp that can be used in WebCoRE
• renamed parseCustomMessage to parseOpenCloseReport
• removed any code related to battery voltage / percentage
• updated deprecated zigbee command code to currently accepted ST zigbee function calls
• added lots of hopefully helpful comment lines
• various reformatting and more logical reordering of function calls

Sources for conversion to Door Control capability:

Since I don’t have the curtain motor, I had to assign the DTH to one of my Zigbee bulbs (which use the same Zigbee on/off commands.) Basic functionality seems to be working great, but I was unable to test the log output for any read attribute messages from cluser 000D / attribute ID 0055. So please let me know if that works for you or not.

On my Mac I use the Chrome browser when I need to keep a Live Logging window open, because Safari times out / logs out after a few hours.

Here are ten open / close events each from the app and manual, using your new DTH.

10 App Open and Close Events

12:26:44 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000] 12:26:43 PM: info Bedroom Curtains: Automatically set state to open after 8 seconds 12:26:35 PM: info Bedroom Curtains: Open command confirmed 12:26:34 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00000000000] 12:26:34 PM: info Bedroom Curtains: Received command to open 12:26:34 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:26:34 PM: info Bedroom Curtains: Sending open command 12:26:19 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000] 12:26:18 PM: info Bedroom Curtains: Automatically set state to closed after 8 seconds 12:26:10 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042c80000] 12:26:10 PM: info Bedroom Curtains: Received command to close 12:26:10 PM: info Bedroom Curtains: Cluster 0006, data = 0 12:26:10 PM: info Bedroom Curtains: Close command confirmed 12:26:09 PM: info Bedroom Curtains: Sending close command 12:26:02 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000] 12:26:00 PM: info Bedroom Curtains: Automatically set state to open after 8 seconds 12:26:00 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000F84100F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00041f80000] 12:25:52 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00000000000] 12:25:52 PM: info Bedroom Curtains: Open command confirmed 12:25:52 PM: info Bedroom Curtains: Received command to open 12:25:52 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:25:51 PM: info Bedroom Curtains: Sending open command 12:25:41 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000] 12:25:40 PM: info Bedroom Curtains: Automatically set state to closed after 8 seconds 12:25:40 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000864200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042860000] 12:25:32 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042c80000] 12:25:32 PM: info Bedroom Curtains: Close command confirmed 12:25:32 PM: info Bedroom Curtains: Received command to close 12:25:32 PM: info Bedroom Curtains: Cluster 0006, data = 0 12:25:31 PM: info Bedroom Curtains: Sending close command 12:25:24 PM: debug refreshing 12:25:15 PM: info Bedroom Curtains: Received command to open 12:25:15 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:25:15 PM: info Bedroom Curtains: Sending open command 12:25:02 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000] 12:25:00 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000904100F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00041900000] 12:24:53 PM: info Bedroom Curtains: Open command confirmed 12:24:52 PM: info Bedroom Curtains: Received command to open 12:24:52 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:24:52 PM: info Bedroom Curtains: Sending open command 12:24:37 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000] 12:24:36 PM: info Bedroom Curtains: Automatically set state to closed after 8 seconds 12:24:35 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000924200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042920000] 12:24:35 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000924200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042920000] 12:24:28 PM: info Bedroom Curtains: Close command confirmed 12:24:27 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042c80000] 12:24:27 PM: info Bedroom Curtains: Received command to close 12:24:27 PM: info Bedroom Curtains: Cluster 0006, data = 0 12:24:27 PM: info Bedroom Curtains: Sending close command 12:24:20 PM: info Bedroom Curtains: Received command to open 12:24:20 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:24:20 PM: info Bedroom Curtains: Sending open command 12:24:08 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000] 12:24:07 PM: info Bedroom Curtains: Automatically set state to open after 8 seconds 12:23:59 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00000000000] 12:23:59 PM: info Bedroom Curtains: Open command confirmed 12:23:59 PM: info Bedroom Curtains: Received command to open 12:23:59 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:23:59 PM: info Bedroom Curtains: Sending open command 12:23:42 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000] 12:23:41 PM: info Bedroom Curtains: Automatically set state to closed after 8 seconds 12:23:40 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000944200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042940000] 12:23:33 PM: info Bedroom Curtains: Close command confirmed 12:23:32 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042c80000] 12:23:32 PM: info Bedroom Curtains: Received command to close 12:23:32 PM: info Bedroom Curtains: Cluster 0006, data = 0 12:23:32 PM: info Bedroom Curtains: Sending close command 12:22:59 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000] 12:22:58 PM: info Bedroom Curtains: Automatically set state to open after 8 seconds 12:22:50 PM: info Bedroom Curtains: Open command confirmed 12:22:49 PM: info Bedroom Curtains: Received command to open 12:22:49 PM: info Bedroom Curtains: Cluster 0006, data = 1 12:22:49 PM: info Bedroom Curtains: Sending open command 12:21:35 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000] 12:21:26 PM: info Bedroom Curtains: Close command confirmed 12:21:25 PM: info Bedroom Curtains: Received command to close 12:21:25 PM: info Bedroom Curtains: Cluster 0006, data = 0 12:21:25 PM: info Bedroom Curtains: Sending close command

10 Manual Open and Close Events

1 - Close

12:39:21 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000]
12:39:20 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000644200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042640000]
12:39:12 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000BC4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042bc0000]

2 - Open
12:41:42 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000]
12:41:40 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000604100F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00041600000]
12:41:34 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000E04000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00040e00000]

3 - Close
12:43:48 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000]
12:43:40 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000BC4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042bc0000]

4 - Open
12:44:28 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000]
12:44:20 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000A04000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00040a00000]
12:44:20 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000A04000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00040a00000]

5 - Close
12:45:02 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000]
12:45:00 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000AC4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042ac0000]
12:44:54 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000BA4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042ba0000]

6 - Open
12:45:51 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000]
12:45:50 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C55003900000C4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f000420c0000]
12:45:43 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000E04000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00040e00000]

7 - Close
12:46:43 PM: info Bedroom Curtains: Automatically set state to open after 8 seconds
12:46:37 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000]
12:46:35 PM: info Bedroom Curtains: Open command confirmed
12:46:35 PM: info Bedroom Curtains: Open command confirmed
12:46:35 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000A04200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042a00000]
12:46:29 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000BC4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042bc0000]

8 - Open
12:47:21 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000]
12:47:20 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000E04100F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00041e00000]
12:47:14 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000604100F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00041600000]

9 - Close
12:48:00 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000000000F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00000000000]
12:47:52 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000BC4200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042bc0000]

10 - Open
12:48:36 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000C84200F02300000000, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0000000023f00042c80000]
12:48:35 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000044200F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00042040000]
12:48:28 PM: info Bedroom Curtains: Unrecognized Read Attribute Message: [raw:39C001000D1C5500390000A04000F02300C03903, dni:39C0, endpoint:01, cluster:000D, size:1C, attrId:0055, encoding:39, value:0339c00023f00040a00000]

I should have checked this before I ran 20 of them, but it looks like the code that’s supposed to catch the cluster and attribute we’re looking for isn’t working. I tried modifying it a couple different ways and didn’t get any different result.

Also, there is a strange event in the middle of the manual sections that looks like some of the automatic code fired? Or the motor sent an on/off event that triggered that code?

I see that, but the “unrecognized message” line still output the relevant data, just without isolating the specific groups of bytes.

My main Mac’s SSD bit the dust yesterday, so it may take me some days to have a look at that output.

Is the DTH working as expected otherwise?

Yeah, it works great, otherwise.
Thank you & good luck with the SSD.