How to convert IR codes from pronto to YAML?

Denon support was kind to send me a sheet containing the discrete IR codes for my Denon PMA-50 amp. So now it’s up to me to convert those codes to YAML which the Broadlink Mini3 IR transmitter can spit out. I’m stuck. Can anyone help?

  1. I found a little tool called Denon Pronto Hex generator that converts the Denon codes to Pronto format.
  2. Then I also found a Python script to convert Pronto codes to Broadlink.
  3. Lastly, someone mentioned you should Base64-encode the output for use in YAML. So I added that to the script.

Although the output seems familiar/fitting, it’s just not doing anything. Can you help?

Edit: here is an output I created for POWERON but it doesn’t do anything:
JgBmAHE4Dg4ODg4qDg4OKg4ODioODg4ODioODg4ODioOKg4ODg4ODg4ODg4ODg4qDioOKg4ODioODg4ODg4ODg4qDioOKg4qDg4OKg4ODg4ODg4ODg4ODg4ODioODg4qDg4ODg4qDgAJlg0F

I’m also facing a similar situation. Did you solve this in the end?

@HomeAssistantUser: I did. Two things I did: 1) figured out a working conversion script and 2) change the number of repeats (most important).

I added some line of code to the aforementioned script. Now it converts straight from Pronto to Broadlink YAML. Here is the script. Just go to https://repl.it, select Python 2.7 and paste the script in there.

# Example code
# I grabbed a random code from remote central.
# http://www.remotecentral.com/cgi-bin/codes/3m/video_projector/
# 
CodesToConvert = [
  # this is one code
  "0000 0070 0000 0032 0080 0040 0010 0010 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0ACE ",
  # this is another code (its actually a copy of the first  code above just as an example, need a comma to seperate codes)
  "0000 0070 0000 0032 0080 0040 0010 0010 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0ACE"]

import binascii
import struct
import sys
import base64



def pronto2lirc(pronto):
    codes = [long(binascii.hexlify(pronto[i:i+2]), 16) for i in xrange(0, len(pronto), 2)]

    if codes[0]:
        raise ValueError('Pronto code should start with 0000')
    if len(codes) != 4 + 2 * (codes[2] + codes[3]):
        raise ValueError('Number of pulse widths does not match the preamble')

    frequency = 1 / (codes[1] * 0.241246)
    return [int(round(code / frequency)) for code in codes[4:]]

def lirc2broadlink(pulses):
    array = bytearray()

    for pulse in pulses:
        pulse = pulse * 269 / 8192  # 32.84ms units

        if pulse < 256:
            array += bytearray(struct.pack('>B', pulse))  # big endian (1-byte)
        else:
            array += bytearray([0x00])  # indicate next number is 2-bytes
            array += bytearray(struct.pack('>H', pulse))  # big endian (2-bytes)

    packet = bytearray([0x26, 0x00])  # 0x26 = IR, 0x00 = no repeats
    packet += bytearray(struct.pack('<H', len(array)))  # little endian byte count
    packet += array
    packet += bytearray([0x0d, 0x05])  # IR terminator

    # Add 0s to make ultimate packet size a multiple of 16 for 128-bit AES encryption.
    remainder = (len(packet) + 4) % 16  # rm.send_data() adds 4-byte header (02 00 00 00)
    if remainder:
        packet += bytearray(16 - remainder)

    return packet

for code in CodesToConvert:
    # get rid of spaces in the code.
    cleanCode = code.replace(" ","")
    # pronto2lirc needs a byte array, convert it
    pronto = bytearray.fromhex(cleanCode)
    # convert the pronto to LIRC pulse format
    pulses = pronto2lirc(pronto)
    # convert LIRC pulse format to broadlink
    packet = lirc2broadlink(pulses)

    print
    print binascii.hexlify(packet)
    print ""
    print base64.b64encode(packet)


# I'm not using this.
# but it was in the original code so I'm leaving it
# if someone compiles a python executable it uses the code below.
if __name__ == '__main__':

    for code in sys.argv[1:]:
        pronto = bytearray.fromhex(code)
        pulses = pronto2lirc(pronto)
        packet = lirc2broadlink(pulses)

        print
        print binascii.hexlify(packet)

With the resulting Broadlink codes, I changed the number of repeats. This way, the IR code doesn’t get blasted just once but 5x in a row. This was key, now my Denon amp is picking up the IR signals consistently.

Repeats can be changed on this website, tab Change Repeats:
https://dimagoltsman.github.io/Random-Broadlink-RM-Code-Generator/#

Let me know if I can be of any more assistance.

Hi Emphyrio,

Thanks so much for sharing! I’ll give it a go and see if it works for me too.

Hi Emphyrio,
could you share the pma-50 discrete code? denon not sent me…
then i can try…
Thanks

@matrix Here is a ZIP containing the relevant IR codes for Denon PMA-50. I also included the script to convert from Pronto to Broadlink YAML and the program to convert from Denon to Pronto.

Download from Dropbox

Thanks a lot, now I have all code in my pronto remote…
If you can…I could learn all the button with the rmmini 3 and shre the codes if you want…

Nice offer. Would be nice if you would post the codes here. Don’t go out of your way though :):slightly_smiling_face:

Edit: I just noticed you didn’t convert to yaml. Then it’s not that useful for me, the steps to convert to yaml are the most time consuming. Thanks anyway!

You might be interested at GitHub - lbschenkel/broadlink-bridge: Bridge to Broadlink devices supporting REST, MQTT and LIRC protocols

Hi there. I realize this is an old thread but I’m at a loss and really need some help. I have a Denon PMA-800NE amp and they sent me a similar chart with IR codes. I can’t for the life of me figure out what to type into the Pronto Hex generator to get the right codes. I’ve searched all over and can’t figure it out. Could you give me some direction? I would appreciate it greatly. I’ve pulled what’s left of my hair out trying to do this. Thanks!

Can you upload the Denon document? Perhaps I can take a look for you.

Edit: took some screenshots from my documentation. Here they are:


Right-click the device & select Genre 1 code (number 1):

Same for Genre 2 (number 2):

Tick the check box for ‘Enter function in decimal or hex’ then input the function code (number 3):

Click Generate Hex Code.

@Xanadu1209 I’m curious, did you succeed with your Denon amp?

Amazing man!..thanks so much!..I was able to get HDMI1 to 4 codes from remotecentral and produce working broadlink codes for my Lg Tv!!..Amazing, because I did’t now have those direct input buttons on any of my remotes so no chance to teach those codes to my broadlink or switchbot hub minis…With the produced broadlink codes my Lg Tv’s can switch directly to an specific input, even my old Tvs without webos, etc…Since I have only one broadlink rm4 pro and a bunch of switchbot hub mini distributed around the hose, I use the “new learned” HDMIx codes send it by the rm4 pro to teach the hub mini’s the same commands, so now all IR blasters on the house knows how to switch a Lg tv to the desired input, less delay also than making switchbot API calls…

Thanks again!

Can you tell me how you converted the remotecentral codes into Broadlink format? I’m struggling to get the Pronto Hex Codes on there for a device into the Jgxxxxx format.

I believe there must be smarter ways nowadays, but perhaps this is still working for you.

Go to Paizio Python2 Online and copy/paste the script below. Copy your own Pronto Hex codes in the appropriate place & execute.

With the resulting Broadlink codes, you can (and probably should) change the number of repeats. This way, the IR code doesn’t get blasted just once but e.g. 5x in a row. This was key for my Denon amp to pick up the IR signals consistently. Repeats can be changed on this website, tab Change Repeats:
https://dimagoltsman.github.io/Random-Broadlink-RM-Code-Generator/#

Script:

# Example code
# I grabbed a random code from remote central.
# http://www.remotecentral.com/cgi-bin/codes/3m/video_projector/
# 
CodesToConvert = [
  # this is one code
  "0000 0070 0000 0032 0080 0040 0010 0010 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0ACE ",
  # this is another code (its actually a copy of the first  code above just as an example, need a comma to seperate codes)
  "0000 0070 0000 0032 0080 0040 0010 0010 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0ACE"]

import binascii
import struct
import sys
import base64



def pronto2lirc(pronto):
    codes = [long(binascii.hexlify(pronto[i:i+2]), 16) for i in xrange(0, len(pronto), 2)]

    if codes[0]:
        raise ValueError('Pronto code should start with 0000')
    if len(codes) != 4 + 2 * (codes[2] + codes[3]):
        raise ValueError('Number of pulse widths does not match the preamble')

    frequency = 1 / (codes[1] * 0.241246)
    return [int(round(code / frequency)) for code in codes[4:]]

def lirc2broadlink(pulses):
    array = bytearray()

    for pulse in pulses:
        pulse = pulse * 269 / 8192  # 32.84ms units

        if pulse < 256:
            array += bytearray(struct.pack('>B', pulse))  # big endian (1-byte)
        else:
            array += bytearray([0x00])  # indicate next number is 2-bytes
            array += bytearray(struct.pack('>H', pulse))  # big endian (2-bytes)

    packet = bytearray([0x26, 0x00])  # 0x26 = IR, 0x00 = no repeats
    packet += bytearray(struct.pack('<H', len(array)))  # little endian byte count
    packet += array
    packet += bytearray([0x0d, 0x05])  # IR terminator

    # Add 0s to make ultimate packet size a multiple of 16 for 128-bit AES encryption.
    remainder = (len(packet) + 4) % 16  # rm.send_data() adds 4-byte header (02 00 00 00)
    if remainder:
        packet += bytearray(16 - remainder)

    return packet

for code in CodesToConvert:
    # get rid of spaces in the code.
    cleanCode = code.replace(" ","")
    # pronto2lirc needs a byte array, convert it
    pronto = bytearray.fromhex(cleanCode)
    # convert the pronto to LIRC pulse format
    pulses = pronto2lirc(pronto)
    # convert LIRC pulse format to broadlink
    packet = lirc2broadlink(pulses)

    print
    print binascii.hexlify(packet)
    print ""
    print base64.b64encode(packet)


# I'm not using this.
# but it was in the original code so I'm leaving it
# if someone compiles a python executable it uses the code below.
if __name__ == '__main__':

    for code in sys.argv[1:]:
        pronto = bytearray.fromhex(code)
        pulses = pronto2lirc(pronto)
        packet = lirc2broadlink(pulses)

        print
        print binascii.hexlify(packet)

Thanks very much for this code. If anyone else is interested in using it locally, I’ve modified it so it now works with Python 3 (on linux at least).

import binascii
import struct
import base64

def pronto2lirc(pronto):
    codes = [int(binascii.hexlify(pronto[i:i+2]), 16) for i in range(0, len(pronto), 2)]

    if codes[0]:
        raise ValueError('Pronto code should start with 0000')
    if len(codes) != 4 + 2 * (codes[2] + codes[3]):
        raise ValueError('Number of pulse widths does not match the preamble')

    frequency = 1 / (codes[1] * 0.241246)
    return [int(round(code / frequency)) for code in codes[4:]]

def lirc2broadlink(pulses):
    array = bytearray()

    for pulse in pulses:
        pulse = int(pulse * 269 / 8192)  # 32.84ms units

        if pulse < 256:
            array += bytearray(struct.pack('>B', pulse))  # big endian (1-byte)
        else:
            array += bytearray([0x00])  # indicate next number is 2-bytes
            array += bytearray(struct.pack('>H', pulse))  # big endian (2-bytes)

    packet = bytearray([0x26, 0x00])  # 0x26 = IR, 0x00 = no repeats
    packet += bytearray(struct.pack('<H', len(array)))  # little endian byte count
    packet += array
    packet += bytearray([0x0d, 0x05])  # IR terminator

    # Add 0s to make ultimate packet size a multiple of 16 for 128-bit AES encryption.
    remainder = (len(packet) + 4) % 16  # rm.send_data() adds 4-byte header (02 00 00 00)
    if remainder:
        packet += bytearray(16 - remainder)

    return packet

if __name__ == '__main__':
    import sys

    for code in sys.argv[1:]:
        pronto = bytearray.fromhex(code)
        pulses = pronto2lirc(pronto)
        packet = lirc2broadlink(pulses)

        print()
        print("b64:"+base64.b64encode(packet).decode('utf-8'))

I used this to convert codes I pulled directly from RC: Infrared Hex Code Database: Samsung TV Functions Commands (Page 1) to get my samsung tv working with broadlink. It was the only way, because the smart remote that came with my TV is a bluetooth remote and the only IR command it sends is for the power button. And the only thing the samsung HA integrations (core or HACS) are able to do is shut it off.

1 Like