New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
tobiaswaldvogel opened this Issue Jan 23, 2017 · 11 comments

Comments

Projects
None yet
9 participants
@tobiaswaldvogel
Contributor

tobiaswaldvogel commented Jan 23, 2017

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

This comment has been minimized.

Show comment
Hide comment
@tecteun

tecteun Feb 13, 2017

0xd7 for 315Mhz

tecteun commented Feb 13, 2017

0xd7 for 315Mhz

@tobiaswaldvogel

This comment has been minimized.

Show comment
Hide comment
@tobiaswaldvogel

tobiaswaldvogel Feb 15, 2017

Contributor

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

Contributor

tobiaswaldvogel commented Feb 15, 2017

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

@Tobiaqs

This comment has been minimized.

Show comment
Hide comment
@Tobiaqs

Tobiaqs Feb 28, 2017

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!

Tobiaqs commented Feb 28, 2017

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

This comment has been minimized.

Show comment
Hide comment
@appden

appden Mar 10, 2017

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. 👍

appden commented Mar 10, 2017

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. 👍

@tobiaswaldvogel

This comment has been minimized.

Show comment
Hide comment
@tobiaswaldvogel

tobiaswaldvogel Mar 16, 2017

Contributor
Contributor

tobiaswaldvogel commented Mar 16, 2017

@dimkaram

This comment has been minimized.

Show comment
Hide comment
@dimkaram

dimkaram Mar 18, 2017

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!

dimkaram commented Mar 18, 2017

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

This comment has been minimized.

Show comment
Hide comment
@pavram

pavram Jul 30, 2017

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.

pavram commented Jul 30, 2017

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

This comment has been minimized.

Show comment
Hide comment
@marcoalexpinheiro

marcoalexpinheiro Oct 3, 2017

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!

marcoalexpinheiro commented Oct 3, 2017

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

This comment has been minimized.

Show comment
Hide comment
@pavram

pavram Oct 5, 2017

@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:

  • 0x0f, 0x0e (Lead-ins lets call these both 0x0f) => 480 Microseconds (ms)
  • 0x06 and 0x07's, => 0x06 (6) => 192 Microseconds
  • 0x0A's and 0x0B's. => 0x0B (11) => 352 Microseconds

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.)

pavram commented Oct 5, 2017

@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:

  • 0x0f, 0x0e (Lead-ins lets call these both 0x0f) => 480 Microseconds (ms)
  • 0x06 and 0x07's, => 0x06 (6) => 192 Microseconds
  • 0x0A's and 0x0B's. => 0x0B (11) => 352 Microseconds

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.)

@tomhoplon

This comment has been minimized.

Show comment
Hide comment
@tomhoplon

tomhoplon Feb 5, 2018

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.

tomhoplon commented Feb 5, 2018

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

This comment has been minimized.

Show comment
Hide comment
@R0nd

R0nd Jul 12, 2018

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.

R0nd commented Jul 12, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment