mjg59 / python-broadlink

Python module for controlling Broadlink RM2/3 (Pro) remote controls, A1 sensor platforms and SP2/3 smartplugs
MIT License
1.39k stars 479 forks source link

Additional info for generating data for IR/RF from LIRC DB etc. ... #57

Open tobiaswaldvogel opened 7 years ago

tobiaswaldvogel commented 7 years ago

Last week I received my RM2 Pro and did some reverse engineering on the data required for command 2. I am using this mainly as an xPL to RF/IR gateway running on my router (OpenWRT/LEDE), therefore all my development is done in plain C rather than python, as this would be an overkill for a small router device. Nevertheless this project helped me a lot and therefore I wanted to share my results, in case that someone wants to implement it in Python.

Data for sending an IR/RF command (payload for the send command)

Offset Meaning
0x00 0x26 = IR, 0xb2 for RF 433Mhz
0x01 repeat count, (0 = no repeat, 1 send twice, .....)
0x02, 0x03 Length of the following data in little endian
0x04 .... Pulse lengths in 32,84ms units (ms * 269 / 8192 works very well)
.... ....
.... 0x0d 0x05 at the end for IR only

Each value is represented by one byte. If the length exceeds one byte then it is stored big endian with a leading 0.

Example: The header for my Optoma projector is 8920 4450 8920 269 / 8192 = 0x124 4450 269 / 8192 = 0x92

So the data starts with 0x00 0x1 0x24 0x92 ....

If you use LIRC as a template then you have just to continue with pre-data and then command, where you would use the "zero" pulse lengths for 0 and the "one" pulse lengths for 1

It seems that infrared commands need to be terminated always with 0x0d 0x05 in addition, whereas this is not required for RF. I didn't figure out the meaning of this so far.

So far I was able to produce all IR commands for my devices as well as for all RF devices. I have quite a bunch of RF devices, like remote controllable sockets and switches and a projection screen. For most of them I was not able to learn the RF code with the RM2 PRo, but as I knew the timings already generating the codes works perfectly well.

If you have any questions or you need help let me know. I will publish soon the C code of my xpl gateway on GitHub, if someone is interested.

One more thing: If you don't want your device to connect back home to China or to talk to Amazon then you better block outgoing traffic for your device.

tecteun commented 7 years ago

0xd7 for 315Mhz

tobiaswaldvogel commented 7 years ago

Thanks for that :-) I think with this we have now all the pieces together

Tobiaqs commented 7 years ago

Hello,

I was wondering if someone could help me translate a LIRC remote profile into a Broadlink command payload. I want to control my old Philips FA 330 Amplifier with my Broadlink RM3 Mini. I've been playing with the python-broadlink library for a while now and I know how to capture codes and replay them. I don't own the remote that belongs to the device.

I found this remote profile in LIRC's database. This is not the remote for my exact device, but I figured that it might work, since their functionality is quite similar. I am struggling to convert it to a usable format. Even though the above information is very helpful, I don't quite understand how to write down a command in pulse lengths. Thanks in advance for the help!

appden commented 7 years ago

Here's a Gist of a Python program that converts Pronto IR hex codes to LIRC and then to Broadlink commands according to this specification. I've successfully converted dozens of Pronto codes with it. I hope it saves somebody the trouble of recreating it!

One thing I think wasn't mentioned is that the command needs to be padded with zeros at the end so that after rm.send_data() adds the 4-byte preamble, the payload byte count will be a multiple of 16 (so it can be AES 128-bit encrypted).

@tobiaswaldvogel thanks for detailing this protocol. I hope @mjg59 will merge your PR with the protocol spec updates. :+1:

tobiaswaldvogel commented 7 years ago

Hi Dimitris,

actually you are right, it is a 24bit, here are some hints how to read it:

The first one:

b2 RF

08  Repetitions

34 00   52 bytes follow (big endian)

Afterwards there is a series of 24 0d and 0d 24 (0c and 23 are the same, there is some tolerance). Let's interpret long-short (24 0d) as 1 and short-long (0d 24) as 0.

Then there is one sequence 0c 00 01 6f. This is the footer. 0c is short as always and 00 01 6f means 016f. It seens that the BL device is not smart enough to detect the footer as end, but as there are repetions it works anyway.

So let's start to write down the pairs after the footer and at the end switch over to the start. Then we have:

24 0d, 0c 24, 0c 24, 0c 24 ..... 0c 24, 0c 00 01 6f

If we interpret the bits and write it in hex we get: 8074a4

If you do the same for the second one you get: 8074a8

In the 3rd and 4th one the BL device was not able to detect that it is a repetion. Therfore the repeat count is 0. We can pick any sequence between two footers and get 8074a2 or the 3rd and 8074a1 for the 4th.

So it seems that the first 20bits are the device ID and then each bit 21..24 is representing one button.

If you want more buttons I would try to increment the ID by one, so e.g. 8074b8, 8074b4, 8074b2, 8074b1

The sequence would be then:

b2 RF

08 Repetitions

34 00   52 bytes follow (big endian)  24 pairs + 4 for the footer

       24 0d for a 1, 0d 24 for a 0

0c 00 01 6f   (Footer)

Cheers,

Tobias

-----Ursprüngliche Nachricht----- Von: dimkaram notifications@github.com Gesendet: Don 16 März 2017 16:47 An: mjg59/python-broadlink python-broadlink@noreply.github.com CC: Tobias Waldvogel tobias.waldvogel@trustanywhere.com; Mention mention@noreply.github.com Betreff: Re: [mjg59/python-broadlink] Additional info for generating data for IR/RF from LIRC DB etc. ... (#57)

Hi All and thanks for the fantastic work that you have been doing here!

First of all, apologies for the long post. Also, I don't have much experience on electronics or programming, but I am keen to try and learn.

So, I am using this script as part of Home Assistant. Among other devices, I want to control this RF 3-gang light switch: http://www.ebay.co.uk/itm/182305423992?_trksid=p2057872.m2749.l2649 http://www.ebay.co.uk/itm/182305423992?_trksid=p2057872.m2749.l2649

It has 3 buttons, and each one can be programmed to 3 commands: toggle, on and off, i.e. a total of 9 commands. However, the remote that comes with it only has 4 buttons, so I can only produce 4 codes. I am using these codes for toggling switch 1, toggling switch 2, toggling switch 3 and switching everything off. This is OK for normal use, however, for home automation purposes, I want to have different codes for explicitly switching each switch on and off. To make the long story short, I want to generate 6 additional RF commands for my Broadlink device, so that I can program each switch to turn on and off when these commands are transmitted.

I found out that the remote has an ev1527 chip, where it also says 1410 (I suppose this is a pin). I have obtained the hex codes for the 4 buttons of my remote, and they are as follows:

b2083400240d240d230d0c24240d0c250c25230d0c25240d0c250c24230d0c250c250c00016f240d0c240c240c250c240c250c250c250c2400000000

b21034000c250c240c24240d240d240d0c24230d0c240c24240d0c25230d0c25240d0c250c250c240c00016f230d0c240c250c250c250c2400000000

b200ca0004000185240c0c23230c0c230c240c23240b0c230d00016d240b0c230c240c230c230c230c230d230c23240b240c230c0c23240b0d230c23240b0c23240c0c230c230c23240c0c230c00016e230c0c230c230d230c230c230c230c240c23240b240b240c0c23240b0c240c23240b0c23240c0c230c230c23240c0c230c00016e240b0c230c240c230c230c230c240c230c23240b240b240c0c23240b0d220d23240b0c23240c0c230c230c24230c0c230c00016e240b0c230d230c230c230c230c240c230c23130005dc0000000000000000000000000000

b2006c000c000172240c0c240c240c230d230d230d230c240c24240c240c240c0c23250b0d230d23240c0c24240c0c240c240c230d23250b0d000172240c0c230d230c240c240c240c240c240c23250b250b250b0c24240c0c240c24240c0c24240c0c240c240c230c24240c0d0005dc000000000000000000000000

Clearly, they all start with b2 as expected. Second byte varies from 00 to 10 for different buttons. Third and fourth byte are indeed the length of the following data in little endian (the rest is filled with zeros).

I have also found out that the ev1527 should be transmitting 24bit codes. However, the values that I can see don't make any sense to me (even their length is not always a multiple of 24bits!). Does anyone have any idea on how I can understand what these codes are and/or how I could possibly produce the 6 additional ones that I actually need?

Many many thanks, Dimitris

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

 

dimkaram commented 7 years ago

Wow! Thank you very much for your time and your detailed response! It took me some time to implement this but it actually works! Thanks again!

pavram commented 7 years ago

So, I've been struggling to understand the actual protocol, because there are many sources of remote control data, and I really wanted to understand what the format was actually doing.

The Pronto -> LIRC -> broadlink format shifter was cruicial to understanding it, and appden probably understands what was going on, but it took me a long time to finally understand what was happening.

This isn't really that useful for people to know, but I finally fully understand what the broadlink protocol is. tobias' description above isn't quite right. It might be appropriate for some IR protocols, but not for all of them. (tobias might know this already, but the description above didn't actually explain the protocol for me properly).

As I say; this is going too in depth, but I needed to understand it for myself so I thought I might describe it anyway.

So, in large part the protocol is as described above.

offset values description
0x0 0x26 - IR as described above, 0x26 for IR, 0xb2 for RF 433 etc
0x01 repeats as above
0x02-0x03 remaining length as above, big endian
0x04+ duration until next change each single byte (zero indicates that the next value is 2 bytes long)

Now, if you read tobias' description above you might be confused. above he describes IR commands representing "0" and "1" using 2 seperate bytes. For some IR encoding schemes this is accurate. but read on for why.

Each of these duration values, represents the duration until the next "change" in IR brightness.

Some IR schemes represent 1's and 0's with a full up and then down pulse, and associated durations. (this is the scheme tobias described above) In this instance, you can describe the "1"s and "0"s using each of the distinct 2 byte pairs.

For different IR encoding schemes however (the one I unfortunately was investigating!) the 1's and 0's are encoded slightly differently. in the RC6 scheme, it is slightly condensed.

Specifically in RC6 it is the movement of "low" to "high" that represents a 1, and the movement from "high" to "low" that represents a 0. You might be thinking to yourself, so? that sounds the same! but it isn't. The data is condensed. It takes varying numbers of bytes to describe different values.

it is easiest to show the difference when you look at consecutive numbers.

(header of this table represents the "duration" of the time-slice)

entry 0e 0e 0e 0e RMCode
00 ___ ^^ ___ ^^ 0e0e0e0e
01 ___ ^^ ^^ ___ 0e1d0e (the high signal is two units of 0e long, thus 1d)
10 ^^ ___ ___ ^^ 0e1d0e (!!)
11 ^^ ___ ^^ ___ 0e0e0e0e

Notice how the value of 00 and 11 are the same codes, and the values of 01 and 10 are also the same (and also only 3 bytes not 4 bytes long). This kind of encoding is more efficient, but the actual value being transmitted, relies on the previous state. So, 01 and 10 are the same, but their initial conditions were different. The initial condition was low or high, which changed what the subsequent value would be.

TLDR So, ultimately, the actual byte values in the broadlink codes are the duration that the IR transmitter spends in the next "state" either the "high" state or the "low" state (depending on the first state it was in, presumably the very first duration value is the "high" state).

other than the 0d0f at the very end, and the first 4 bytes for the type-repeat and lengthofpacket bytes, every single byte (or 2 bytes when there is a leading zero) represents a duration. but does not explicitly represent a 1 or a 0, or even if it is a "high" pulse of a "low" pulse. It is a duration until you go "high" or go "low".

Just in case someone was wondering how this all worked! (it was doing my head in!)

RC6 description (the windows media center remote uses the RC6 protocol) http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/index.php?topic=worklog&p=0

the Pronto->Lirc->broadlink was critical for my understanding of this. But I needed it in context of the RC6 protocol.

Importantly, not all IR protocols are the same. Some of them really are as simple as looking at 2 bytes at a time to get a 1 or 0, but the RC6 protocol requires that you know every byte that came before, before you can know if you are looking at a 1 or a 0.

marcoalexpinheiro commented 7 years ago

Hello,

I'm trying to do some RF reverse engineering with a roller shutter switch that I bought at aliexpress. For some reason they encoded the signal in some way that none of my traditional RF remotes can emit signal to it (i think is a way of sell specific specific remote control). BUT, with RM PRO app (e-control) I finally downloaded some working codes from their cloud but now I want to understand it (to emit RF signals from a custom RF gateway that I'm building). Is it possible to extract this:

1) bits length 2) RF protocol (433_1, 433_2, ...) 3) RF pulselength (tried 315ms)

from here?

0xB2 0x3D 0x32 0x00 0x0F 0x0E 0x07 0x0A 0x07 0x0B 0x06 0x0A 0x0B 0x06 0x0A 0x07 0x0A 0x07 0x0B 0x07 0x0A 0x07 0x07 0x0B 0x0A 0x07 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0A 0x07 0x0A 0x07 0x0A 0x07 0x0A 0x0A 0x07 0x0A 0x07 0x07 0x0A 0x06 0x0B 0x07 0x0A 0x06 0x0B 0x0A 0x07 0x00 0x00 0x00 0x00 0x00 0x00

Thank you very much!

pavram commented 7 years ago

@marcoalexpinheiro Hi Marco,

so starts with 0xb2, so it is 433 mhz. (just states the frequency that the pulses are done at, has nothing to do with the "protocol")

0x3d = 61, this implies that it repeats the following sequence 61 times. I have zero experience with RF transmitters and don't know if this is a sane value. (IR this value is usually more like zero or 1 or sometimes 2).

0x32 0x00 = 50, indicates 50 bytes of "data" to follow. Unlike IR, RF data appears to be all "pulse information" which is to say, there is no pattern at the end of a transmission.

All of the remaining bytes represent durations spent either "high" or "low". Those durations should be roughly the same. The only exceptions to this are usually the "lead ins".

Your packet contains:

As per Tobias's post above, each value is multiples of ~32.84ms. so 32 * 6 = 192 (note: these are microseconds, not milliseconds)

let us assume that this is a simple encoding scheme (not like the RC6 IR protocol) and that each following two bytes represents either a 0 or a 1.

Using Tobias' example above, Long-Short can be 1, and Short-Long can be 0

So your data becomes:

0xB2 0x3D 0x32 0x00 0x0F 0x0F     0x06 0x0B 0x06 0x0B 0x06 0x0B 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x06 0x0B 0x0B 0x06 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x0B 0x06 0x0B 0x06 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x06 0x0B 0x0B 0x06

So lead in with a pulse that goes high for 480ms, then low for 480ms Then a 0 is represented by 0x06 0x0B, or high for 192ms followed by low for 352ms A 1 is represented by 0x0B 0x06, or High for 352ms followed by low for 192ms

I don't know if these durations mean anything to you or the documentation for your transmitter, but hopefully the above helps.

(for what it is worth, using the above your code is: 0001 1111 0100 0000 0110 0001 => 1F4061, which appears to be a 24 bit number in a similar vein to the message Tobias was helping to decode above.)

ghost commented 6 years ago

Sorry, I'm likely posting this in the wrong place. I have the correct code for the remote button I want to imitate but I need to be able to imitate a "long press" for several seconds. Does anyone know if this can be done on RM3 mini, and if so, how.

R0nd commented 6 years ago

I tried to use the frequency identifier 0xd7 to transmit on 315MHz, but it didn't work. So I decided to just brute force the id and listen to the radio on rtl-sdr. Found out that codes 0xaa to 0xac work for me. I have an RM pro without a number, really hard to identify these devices tbh.

Correction - codes 0xaa through 0xbd are picked up on frequencies from 314.729 to 324.228. There's 500kHz between adjacent codes. BUT the 315MHz signal from the RM pro is so weak I doubt it can be useful for any practical purposes. It's way weaker than a 315 remote control. I might be doing something wrong though, will update.