Norman TDBU blind control

My next attempt when i get some time is to just capture a number of actions and rotate through them instead of trying to construct the new ones. If there’s no embedded counter, then I should be able to capture 3 of each button and enabled blinds combination and rotate through them (make sure the requests don’t repeat). If that works, then we could ignore the checksum part.

Although I hope that dumping the firmware from the hub would allow us to figure out exactly how the messages are constructed.

That’s ignoring the checksum validation, right?

Yes - ignoring the checksum - that was based on a NRF sniffer.

I think payload sizes are too large for the NRF24 module I was using which seems to have a 32 byte limit in fixed payloads (later captures were approx the same size as your HackRF captures)

The protocol itself seems to allow 252 bytes in fixed size payloads. Sourcing a NRF52 dev board to see if that helps.

There’s a chance that these are actually two separate messages, both starting at 0xaa. Even if not, you could pretend they are by matching on sync 16f3 :slight_smile:

A small update. With the power of a SAT solver, I got some parts of the checksum figured out. Now I know that it’s CRC16 with a non-standard poly 0x0083. It’s independent of the remote. All transmissions finish on a final 1 bit, which is not part of the ending checksum. Not sure about the boundaries of the message and init value yet… Needs more playing around.

This is significant, because with a partial crc state from the middle of the message we can validate/generate the correct checksum without understanding the whole structure. Just writing more code to figure out the init value that would include the remote id.

1 Like

That absolutely explains the behavior I’ve been seeing. I have ~10 shades in my house and some of them occasionally won’t open when I try to open all shades in the house. When I saw the taskID, I was hoping there was some kind of ACK that could be tracked by the taskID but kept coming up empty.

@keito on your integration, it might be nice for it to hit /NM/v1/status shortly after an action occurs, if the shade’s position doesn’t match what was originally requested, try resending.

More specifically (this includes the blinds/remote selector), the CRC for the last 64 bits is CRC16, poly=0x0083, init=0x5473, no reflections. Still not sure where the calculation starts… but getting closer.

@viraptor

I’ve got sample payloads of

18 d7bda 3 f8ec52faa16f3959836ba32204 4950a964 58 a5f5 4772 72b3 e484
18 d7bda 3 f8ec52faa16f3959836ba32204 4950a964 58 a5f5 f822 72b3 3657
18 d7bda 3 f8ec52faa16f3959836ba32204 4950a964 58 a5f5 c26c 72b3 3c9d
18 d7bda 3 f8ec52faa16f3959836ba32204 4950a964 58 a5f5 e441 72b3 1f15

which I’m currently interpreting as
length?: 18 (I’m seeing some longer messages intermittently with different values here)
header: d7bda
command: 3
constant: f8ec52faa16f3959836ba32204
remote id: 4950a964
selected blinds: 58
constant?:a5f5
message id / timestamp: 4772
footer: 72b3
checksum: e484

$ reveng -w16 -s 18d7bda3f8ec52faa16f3959836ba322044950a96458a5f5477272b3e484 18d7bda3f8ec52faa16f3959836ba322044950a96458a5f5f82272b33657 18d7bda3f8ec52faa16f3959836ba322044950a96458a5f5c26c72b33c9d 18d7bda3f8ec52faa16f3959836ba322044950a96458a5f5e44172b31f15

width=16 poly=0x0083 init=0xacc8 refin=false refout=false xorout=0x0000 check=0xf473 residue=0x0000 name=(none)

matching poly on the crc - I’m excluding address from crc calculation.

Yup, that matches my experiments so far. Thanks for confirming your values :slight_smile:

message id / timestamp: 4772

Their marketing material refers to a rolling code - tying a brute force approach on the message id looks like the final 2 characters follow a set pattern

16 codes in sequence with the final character the same, and the 3rd character follows a repeating sequence within each of the 16 code blocks. Resulting in a repeating pattern every 256 codes.

The first 2 characters appear more random.

There doesn’t appear to be a consistent interval for the full 4 characters.

Given the devices have to sync the rolling code with a single message I’m suspecting that the first 2 characters are random - but that seems too simple.