IR remote to template light with all controls

I just managed to create a template light that sends the commands via IR blaster.
It can do all colors (from a 24 key IR remote, but it can easily be expanded for larger remotes), brightness and effects.

image

The only limitation is that you can’t get saturation, so my way of solving that is if you click where the saturation is more than 70% then it gets converted to 100%, less than 70 is 0% (white light).

Because the 24 key remotes do not have all colors then clicking on the wheel where there is no corresponding button on the remote “rounds” the click to the closest color.

The IR blaster is a ready made ESP device sold on aliexpress.
I use ESP-Home to control the blaster.

ESP-Home yaml:

remote_receiver:
  pin:
    number: GPIO14
    inverted: true
    mode:
      input: true
      pullup: true
  dump: lg
  
  
remote_transmitter:
  pin: GPIO4
  carrier_duty_percent: 50%

button:
  - platform: template
    name: "David TV backlight on"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFE01F
          nbits: 32       

  - platform: template
    name: "David TV backlight off"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF609F
          nbits: 32       

  - platform: template
    name: "David TV backlight flash"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFF00F
          nbits: 32       

  - platform: template
    name: "David TV backlight strobe"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFE817
          nbits: 32       

  - platform: template
    name: "David TV backlight fade"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFD827
          nbits: 32       

  - platform: template
    name: "David TV backlight smooth"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFC837
          nbits: 32      
          
  - platform: template
    name: "David TV backlight none"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFD02F  # makes it white
          nbits: 32      

  - platform: template
    name: "David TV backlight dim up"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFA05F
          nbits: 32      

  - platform: template
    name: "David TV backlight dim down"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF20DF
          nbits: 32      
          
######################################################
######## the number represents the hue value ################
######################################################
# column 1

  - platform: template
    name: "David TV backlight 0"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF906F
          nbits: 32      

  - platform: template
    name: "David TV backlight 15"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFB04F
          nbits: 32      
          
  - platform: template
    name: "David TV backlight 30"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFA857
          nbits: 32      

  - platform: template
    name: "David TV backlight 45"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF9867
          nbits: 32      

  - platform: template
    name: "David TV backlight 60"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF8877
          nbits: 32      

######################################################
# column 2
          
  - platform: template
    name: "David TV backlight 120"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF10EF
          nbits: 32      

  - platform: template
    name: "David TV backlight 135"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF30CF
          nbits: 32      

  - platform: template
    name: "David TV backlight 150"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF28D7
          nbits: 32      

  - platform: template
    name: "David TV backlight 165"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF18E7
          nbits: 32      

  - platform: template
    name: "David TV backlight 180"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF08F7
          nbits: 32      

######################################################
# column 3          

  - platform: template
    name: "David TV backlight 240"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF50AF
          nbits: 32      

  - platform: template
    name: "David TV backlight 255"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF708F
          nbits: 32      

  - platform: template
    name: "David TV backlight 270"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF6897
          nbits: 32      

  - platform: template
    name: "David TV backlight 285"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF58A7
          nbits: 32      

  - platform: template
    name: "David TV backlight 300"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FF48B7
          nbits: 32      

######################################################
          
  - platform: template
    name: "David TV backlight W" # white
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0x00FFD02F
          nbits: 32          
      

We need two helpers, one input_number to hold the brightness of the light.
The light we have has 5 brightness steps, because of that I make the input_number 6 steps ( 0-5).
This because the template light has 0 brightness, and I use this to turn off the light.

We also need a input_select with the effects the light has.

Light template (configuration.yaml):

light:
  - platform: template
    lights:
      david_tv_backlight:
        friendly_name: "David TV backlight"
        level_template: "{{ (states('input_number.david_tv_backlight_brightness')|int) * (255/6) }}" 
        turn_on:
          service: button.press
          data: {}
          target:
            entity_id: button.david_tv_backlight_on
            
            
        turn_off:
          - service: button.press
            data: {}
            target:
              entity_id: button.david_tv_backlight_off
          - service: input_number.set_value
            data:
              value: 0
              entity_id: input_number.david_tv_backlight_brightness
              
              
        effect_list_template: "{{ state_attr('input_select.david_tv_backlight_effects', 'options') }}"
        effect_template: "{{ states('input_select.david_tv_backlight_effects') }}"

        # brightness is optimistic, so it remembers the brightness since last use, and assumes 
        # the brightness is the same. It will not work properly if you use the real remote.
        set_level:
          - if:
              - condition: template
                value_template: "{{ (brightness / (255/6)) | round  == 0 }}"
            then:
              - service: button.press
                data: {}
                target:
                  entity_id: button.david_tv_backlight_off
              - service: light.turn_off
                data: {}
                target:
                  entity_id: light.david_tv_backlight
            else:
              - repeat:
                  count: "{{ (((brightness / (255/6)) | round) - states('input_number.david_tv_backlight_brightness')| int) | abs }}"
                  sequence:
                    - if:
                        - condition: template
                          value_template: "{{ ((brightness / (255/6)) | round) > states('input_number.david_tv_backlight_brightness')| int }}"
                      then:
                        - service: button.press
                          data: {}
                          target:
                            entity_id: button.david_tv_backlight_dim_up
                      else:
                        - service: button.press
                          data: {}
                          target:
                            entity_id: button.david_tv_backlight_dim_down    
                    - delay:
                        milliseconds: 500
              - service: input_number.set_value
                data:
                  value: "{{ (brightness / (255/6)) | round  }}"
                  entity_id: input_number.david_tv_backlight_brightness
            
        set_color:
          - service: button.press
            data: {}
            target: 
              entity_id: >-
                  {% if( s > 70 ) %}
                    
                    {% if( h > 60 and h <= 90) %}
                      {% set h = 60 %}
                    {% elif( h > 90 and h < 120) %}
                      {% set h = 120 %}
                    {% elif( h > 180 and h <= 210) %}
                      {% set h = 180 %}
                    {% elif( h > 210 and h < 240) %}
                      {% set h = 240 %}
                    {% elif( h > 300 and h <= 330) %}
                      {% set h = 300 %}
                    {% elif( h > 330 and h < 360) %}
                      {% set h = 0 %}
                    {% endif %}
                    
                    button.david_tv_backlight_{{ (((h / 15) | int) * 15) % 360 }}    
                  {% else %}
                    button.david_tv_backlight_w
                  {% endif %}
                
                
          # this is to round the template light to the same color as we sent to the light.
          # by some reson it doesn't always work that is why I added it twice, that gives it a bit better success rate       
          - service: light.turn_on
            data:
              hs_color: >- 
                  {% if( s > 70 ) %}
                    {% set s = 100 %}
                    
                    {% if( h > 60 and h <= 90) %}
                      {% set h = 60 %}
                    {% elif( h > 90 and h < 120) %}
                      {% set h = 120 %}
                    {% elif( h > 180 and h <= 210) %}
                      {% set h = 180 %}
                    {% elif( h > 210 and h < 240) %}
                      {% set h = 240 %}
                    {% elif( h > 300 and h <= 330) %}
                      {% set h = 300 %}
                    {% elif( h > 330 and h < 360) %}
                      {% set h = 0 %}
                    {% endif %}
                    
                  {% else %}
                    {% set s = 0 %}
                  {% endif %}
                  [{{ (((h / 15) | int) * 15) % 360 }}, {{ s }}]
            target:
              entity_id: light.david_tv_backlight
          - service: light.turn_on
            data:
              hs_color: >- 
                  {% if( s > 70 ) %}
                    {% set s = 100 %}
                    
                    {% if( h > 60 and h <= 90) %}
                      {% set h = 60 %}
                    {% elif( h > 90 and h < 120) %}
                      {% set h = 120 %}
                    {% elif( h > 180 and h <= 210) %}
                      {% set h = 180 %}
                    {% elif( h > 210 and h < 240) %}
                      {% set h = 240 %}
                    {% elif( h > 300 and h <= 330) %}
                      {% set h = 300 %}
                    {% elif( h > 330 and h < 360) %}
                      {% set h = 0 %}
                    {% endif %}
                    
                  {% else %}
                    {% set s = 0 %}
                  {% endif %}
                  [{{ (((h / 15) | int) * 15) % 360 }}, {{ s }}]
            target:
              entity_id: light.david_tv_backlight
                
        set_effect:
          - service: button.press
            data: {}
            target:
              entity_id: button.david_tv_backlight_{{ effect }}

This now gives me a GUI control of an IR controlled light

8 Likes

Hello. Nice template, I am building my own based on yours using scenes from a Tuya IR controler.
But I found that when the light turns on it doesn’t rebember que last brightness status, always returns 0.
I think I can get past that using another input_number that doesn’t get set to 0 on turn_off, but I wanted to make sure that I’m doing everything correctly and that is the present behaviour.

Summing, how does the light get the old brightness value when it is turned on?

Thanks for your work!

I believe the brightness and other things being saved past off depends on the manufacturer.
Some does, some doesn’t.

I’m not sure you can create this here.
You could try using the turn off sequence to set a copy of the brightness before turned of.
But I’m not sure how you are going to do when you turn on, perhaps a loop that loops and sends the signal to dim down, but that will be quite visible and probably annoying.

Maybe I didn’t explain the best way; it is not the light, but the template that sets the brighness to 0 on the turn_off command:

        turn_off:
          - service: button.press
            data: {}
            target:
              entity_id: button.david_tv_backlight_off
          - service: input_number.set_value
            data:
              value: 0
              entity_id: input_number.david_tv_backlight_brightness

On turn_on service there is no way to know the value before. Any suggestions?
I’m gonna try to remove that last piece of code, that sets input_number value to 0, and see how it behaves when turned off (as sson as I get home).
The color approach is very ingenious, congrats! :slight_smile:

EDIT: the removal of the service input_number.set_value on the turn_off command solved it form me; I understand now what you where trying to say: my bulb remembers the last brightness before turning off, so I don’t need that service call; the only downside is that the brightness is set to a positive value even if the lamp is off. But does not affect the behaviour of the template light.