Setting up an RF bridge for a Könighaus LED ceiling heating

The RX500 provides input to the Hoktek chip, decoding the RF. Low voltage, low current. Four connections: Power (5v or 3.3 is OK), ground, onboard curly 433Mhz antenna, and data out. I think I posted a link to the datasheet earlier. A lot of smarts in one chip, a full superhet crystal controlled receiver, filtering, noise rejection, and decoding, all in one package, at ridiculously tiny price. Output is CMOS digital, so should be able to drive an optocoupler input, with maybe a biasing resistor for correct current drive.

Given the LED controller onboard power supply might be switched, floating AC or some other scheme, and your ESP USB power supply might be doing the same or another, the consideration of ground loops, and AC flow arises if you link the two directly. An optocoupler is an elegant approach to introduce electrical isolation while maintaining signal flow.

The Holtek chip specifications say it is designed to have added drive capabilities for LEDs. Holtek is renowned for these kind of chip integrations to reduce chip count while providing solutions IOT designers are looking for.

I want this panel to replace an existing ceiling light with this IR panel/LED light combination.
My assumption was that the LED would default on to its last setting when power is removed/restored but this is not the case: it defaults off.
I’d rather not dig too deep in the panel and modify it since it has a 5 year warranty.

The remote has these buttons: heating, lighting, timer, temp- and temp+.

I think the remote only sends heating and lighting button presses to the panel.
Heating only switches the IR panel on and off.
Lighting switches the light on and off again, each time with a different color mode, so:

on => cool white => off => on neutral white => off => on warm white.

I also found some codes that changes color mode with the LED on so there must be more than just a single command/toggle.

The manual states:

  1. Remote Control Pairing: After turning on the heater, you will hear a beep. Press the lighting button 5 times. The pairing is successful and the process is completed within 10 seconds.
  2. Lighting: Press the lighting button once to activate the lighting function and press the lighting button again to turn off the lighting.
  3. Heating: Press the heating button once to activate the heating function. Press it again to turn off the heating.
  4. Timer: When the heating is turned on, press the timer button to cycle between 1H, 2H, 4H, 6H, and 8H, and to turn off the heating function at the specified time.
  5. Temperature +: When the heating is turned on, press the temperature + button to set the temperature of the heater. When the set temperature is reached, the heating will automatically turn off and restart if the temperature falls below the set value.
  6. Temperature -: When the heating is turned on, press the temperature - button to set the temperature of the heater. When the set temperature is reached, the heating will automatically turn off and restart if the temperature falls below the set value.

What you mean by “found”?

I took some doing to get anywhere: first trying to capture the remote signals with the correct receiver configuration on the ESP, then making sense of the results since they seem bursts of identical messages.

While doing that I stumbled on some traces with different results.
Remember the original remote only has a ‘lighting’ button that does only 1 thing? Here is what I have so far:

light on:


  - platform: template
    name: "Light ON"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 1
          code: [
            705,-96,302,-501,295,-506,684,-119,290,-511,281,-520,690,-111,671,-131,269,-534,666,-136,663,-138,672,-130,
            258,-548,651,-146,654,-148,652,-150,249,-552,249,-553,248,-554,257,-544,247,-555,247,-554,646,-155,245,-554,
            251,-6162,645,-157,244,-557,251,-551,644,-158,242,-559,241,-560,641,-160,640,-162,239,-564,644,-156,636,-166,
            635,-167,241,-562,632,-168,640,-161,631,-173,228,-572,236,-565,229,-576,226,-572,230,-571,229,-572,630,-172,
            227,-571,227,-6186,630,-171,230,-576,224,-574,627,-173,228,-575,235,-567,626,-175,633,-168,229,-573,627,-175,
            624,-178,623,-178,223,-579,622,-179,622,-180,620,-182,220,-582,219,-582,219,-583,218,-583,223,-579,219,-582,
            626,-175,219,-580,217,-6197,627,-173,221,-581,222,-580,620,-181,220,-582,220,-581,620,-181,620,-182,225,-587,
            609,-183,627,-174,617,-185,215,-587,615,-187,615,-187,620,-181,213,-589,212,-590,215,-587,211,-589,213,-589,
            213,-588,613,-187,220,-580,211,-6202,616,-184,223,-580,215,-587,626,-174,216,-586,214,-587,615,-187,614,-189,
            211,-590,613,-188,612,-189,612,-191,209,-593,616,-184,610,-192,609,-193,217,-586,205,-596,205,-596,207,-594,
            208,-593,211,-591,608,-193,206,-592,207,-6206,612,-189,210,-591,212,-590,611,-190,213,-590,208,-594,614,-185,
            611,-190,210,-593,608,-196,606,-193,616,-185,206,-598,605,-195,605,-196,605,-197,203,-603,200,-602,198,-604,
            201,-599,198,-603,199,-601,603,-195,205,-598,205,-6206,611,-187,212,-592,213,-590,606,-194,205,-597,205,-597,
            610,-188,608,-195,205,-602,606,-190,607,-194,606,-196,206,-604,595,-199,611,-190,603,-199,201,-611,195,-607,
            189,-612,190,-610,191,-610,192,-609,593,-201,199,-609,188,-6235,585,-196,203,-604,197,-603,602,-194,205,-604,
            200,-601,599,-196,614,-187,204,-606,598,-195,604,-199,602,-201,199,-613,591,-198,602,-200,601,-202,197,-621,
            180,-617,185,-617,186,-614,193,-609,186,-615,594,-194,200
          ]

light off:

  - platform: template
    name: "Light OFF"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 1
          code: [
            121,-3281,141,-1640,679,-123,273,-529,275,-526,673,-128,271,-532,265,-537,675,-125,663,-140,258,-544,655,
            -147,651,-151,655,-146,248,-555,646,-154,644,-159,641,-161,239,-563,238,-565,236,-564,245,-557,236,-567,234,
            -565,238,-563,637,-162,235,-6180,638,-163,235,-567,237,-566,634,-167,231,-570,232,-570,632,-169,632,-171,
            226,-576,633,-169,626,-175,626,-175,230,-573,623,-179,629,-172,622,-183,219,-581,218,-584,214,-588,214,-586,
            218,-583,217,-584,220,-583,617,-180,214,-6200,619,-182,217,-585,216,-585,618,-183,217,-585,221,-582,615,-185,
            623,-178,214,-589,615,-186,613,-191,609,-192,207,-595,609,-192,610,-191,608,-195,205,-597,204,-596,210,-592,
            206,-595,208,-595,203,-599,202,-598,605,-192,175,-6239,613,-187,209,-594,206,-594,608,-195,204,-598,204,-600,
            603,-194,607,-194,209,-595,603,-198,612,-188,604,-199,201,-601,600,-202,599,-204,605,-195,198,-605,197,-603,
            200,-603,196,-606,196,-603,199,-602,199,-603,599,-198,198,-6214,607,-194,204,-599,199,-603,609,-190,202,-601,
            200,-601,600,-201,600,-206,193,-604,600,-201,599,-202,598,-205,195,-607,601,-199,597,-205,596,-206,199,-605,
            189,-611,191,-610,192,-608,194,-608,195,-608,190,-611,600,-195,195,-6219,597,-204,196,-605,197,-604,598,-203,
            199,-605,194,-607,603,-196,598,-204,196,-605,596,-207,595,-207,599,-202,193,-609,596,-205,591,-212,589,-213,
            188,-612,190,-612,189,-613,192,-610,187,-614,187,-612,190,-610,593,-205,194,-6218,597,-204,197,-605,200,-603,
            595,-206,193,-609,193,-606,596,-205,595,-213,187,-613,596,-202,594,-208,593,-209,192,-611,590,-211,600,-201,
            591,-211,188,-614,189,-614,185,-616,186,-616,187,-612,189,-612,190,-618,583,-209,186,-6225,594,-208,191,-612,
            194,-605,596,-204,195,-609,194,-609,591,-209,603,-197,192,-612,591,-208,592,-212,589,-214,185,-615,590,-211,
            589,-213,587,-216,184,-617,185,-615,188,-614,186,-615,193,-610,184,-617,185,-613,591
          ]

Change color mode while light is on:

  - platform: template
    name: "Change Light Color Temperature"
    on_press:
      - remote_transmitter.transmit_raw:
          code: [
            # Frame 1
            658,-142,254,-549,254,-547,651,-154,257,-542,244,-557,
            664,-136,646,-157,244,-559,642,-159,650,-152,651,-152,
            235,-566,634,-166,636,-166,634,-168,231,-572,228,-574,
            226,-574,242,-563,222,-576,229,-573,628,-173,228,-571,
            234,

            -5800,

            # Frame 2 (IDENTICAL)
            658,-142,254,-549,254,-547,651,-154,257,-542,244,-557,
            664,-136,646,-157,244,-559,642,-159,650,-152,651,-152,
            235,-566,634,-166,636,-166,634,-168,231,-572,228,-574,
            226,-574,242,-563,222,-576,229,-573,628,-173,228,-571,
            234
          ]

So there seems to be more possible than even the original remote does?

Konighaus is mainly an infrared panel manufacturer, I have a feeling they just implemented some random generic LED driver with a relay with generic encoding.

Did you ever read my post #15 ?
That “color mode” signal is precisely same light ON signal you posted before.
10010011 01110111 00000010

So every press ON is rolling the color.

I missed that but you’re totally right!

Here is a more clean version of the codes that works reliably (I couldn’t get rc_switch to work):

heater:

  - platform: template
    name: "Heater ON"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 6
            wait_time: 6ms
          code: [
            600,-200,200,-600,200,-600,600,-200, # 10010110 
            200,-600,200,-600,600,-200,600,-200, # 01011010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,200,-600,200,-600, 200,-600,# 01010101 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200
            ]
  - platform: template
    name: "Heater OFF"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 6
            wait_time: 6ms
          code: [
            600,-200,200,-600,200,-600,600,-200, # 10010110 
            200,-600,200,-600,600,-200,600,-200, # 01011010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,200,-600,200,-600, 200,-600,# 01010101 
            200,-600,600,-200,600,-200,200,-600, # 01101001 
            200
            ]

Light:

  - platform: template
    name: "Light ON"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 6
            wait_time: 6ms
          code: [
            600,-200,200,-600,200,-600,600,-200, # 10010110 
            200,-600,200,-600,600,-200,600,-200, # 01011010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,200,-600,200,-600, 200,-600,# 01010101 
            200,-600,200,-600,600,-200,200,-600, # 01011001 
            200
            ]
  - platform: template
    name: "Light OFF"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 6
            wait_time: 6ms
          code: [
            600,-200,200,-600,200,-600,600,-200, # 10010110 
            200,-600,200,-600,600,-200,600,-200, # 01011010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,200,-600,200,-600,200,-600, # 01010101 
            200,-600,200,-600,200,-600,600,-200, # 01010110 
            200
            ]

The light starts cool after first ‘on’ then neutral and warm every ‘on’ after that, rolling the colors as you mentioned.

What threw me off - and still does - is this command:

  - platform: template
    name: "Light Doubleclick"
    on_press:
      - remote_transmitter.transmit_raw:
          repeat:
            times: 3
            wait_time: 40ms
          code: [
            600,-200,200,-600,200,-600,600,-200, # 10010110 
            200,-600,200,-600,600,-200,600,-200, # 01011010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,200,-600,200,-600,200,-600, # 01010101 
            200,-600,200,-600,600,-200,200,-600, # 01011001 
            
            200,-6200,
            
            600,-200,200,-600,200,-600,600,-200, # 10010110 
            200,-600,200,-600,600,-200,600,-200, # 01011010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,600,-200,600,-200,600,-200, # 01101010 
            200,-600,200,-600,200,-600,200,-600, # 01010101 
            200,-600,200,-600,600,-200,200,-600, # 01011001 
            200
          ]

This basically identical to the ‘on’ code, but then 3 bursts of 40ms in stead of 6ms. The LED driver beeps 2 times indicating 2 commands I assume, so 2x ‘on’.

The color temperature should advance 2 times then but it doesn’t: it goes (very fast)
cool->neutral
then off and doubleclick again:
cool->neutral

and so on, every time.

If it was just advancing the rolling color I would expect:
cool → neutral
off and doublecklick
warm → cool
off and doublecklick
neutral → warm

I also tried several 8bit variations and repeat/delay combinations without result. So I’ll use what I have for ‘DoubleClick’ as my ‘on’ command and have the same color mode every time I switch it on, which works well enough for me (I wanted an IR heater, not spending this amount of time on this :slight_smile: )

So how it behaves with 100ms wait_time? Or with 4 repeats?

Anything less that ~30ms is treated as single command. I’ve tried up to 90ms in 10ms increments and they all behave the same.

Doesn’t make sense to me. But hell knows, maybe the protocol was designed with different remote with more buttons and adapted to that minimalistic one…