Lutron Caseta Pico Remotes and Node-Red

It dims smoothly for me. A single press, as long as you don’t hold it down, should only increment a single step.

Okay, I was referring to holding down the the button to dim.

Got it. That is how it is designed. When holding down, it sends a sequence of brightness changing events. You can tweak the frequency of the loop and the transition time for each brightness step if you want to.

I will look into that, I have the dimming subflow working across 8 picos working with zigbee, hue and lifx lights.

@MizterB love what you did with the Pico set-up. I would love to use your flow in my set-up. Not being a node-red expert yet I see your higher-level flow and the subflow. Is there a pico complete flow or do I have to grab each one you posted in order to duplicate your config in my set-up?v Do I need to link the two flows together? Thanks for sharing and the help!

Yes, you would need both flows - the sub flow is a common button handling component used by the other flow, which handles the mapping of different remotes to different lights and customized button pressing behaviors.

For what it’s worth, I am no longer using node red for my Pico automations. I have converted to native HA automations. The following automation raises a ‘pico_buttonpress’ event for tap, doubletap, and hold events, which can then be consumed by other automations.

  automation:
    ################################################################################
    # AUTOMATION: pico_buttonpress_event 
    # This a common handler for any Pico button press, including lights and fans
    # which raises a custom 'pico_buttonpress' event containing:
    # entity_id: Pico remote
    # button_pressed: on|off|up|down|action
    # press_type: tap|doubletap|hold
    ################################################################################
    - alias: pico_buttonpress_event
      description: "Raise an event when a Pico remote button is pressed"
      mode: single
      # Trigger this when the remote state changes from 'idle'
      trigger:
        platform: event
        event_type: state_changed
      condition: "{{ trigger.event.data.entity_id in states['variable.pico_remotes'].attributes|list
                      and trigger.event.data.old_state.state|int == 0 
                      and trigger.event.data.new_state.state|int != 0 }}"
      action:
        - variables:
            hold_ms: 1000
            tap_ms: 250
            pico_id: "{{ trigger.event.data.entity_id }}"
            button_id: "{{ states(pico_id) }}"
            button_name: >
              {% if button_id|int == 1 %}
                on
              {% elif button_id|int == 2 %}
                action
              {% elif button_id|int == 4 %}
                off
              {% elif button_id|int == 8 %}
                up
              {% elif button_id|int == 16 %}
                down
              {% endif %}
            button_start: "{{ as_timestamp(now()) }}"
        # Wait for the button to be released
        # While pressed, trigger the 'hold' action every 'hold_ms' millesconds
        # Don't iterate more than 10 times if the sensor gets 'stuck' during a long hold
        - repeat:
            until: "{{ is_state(pico_id, '0') or repeat.index >= 10 }}"
            sequence:
              - wait_template: "{{ states(pico_id) == '0' }}"
                timeout:
                  milliseconds: "{{ hold_ms }}"
              - condition: template
                value_template: "{{ (((as_timestamp(now()) - button_start|float)*1000)|int) >= hold_ms }}"
              # Hold actions
              - service: system_log.write
                data:
                  message: "{{ pico_id }} - Holding button '{{ button_name }}'"
                  logger: pico_buttonpress
                  level: debug
              - event: pico_buttonpress
                event_data: 
                  entity_id: "{{ pico_id }}"
                  button_pressed: "{{ button_name }}"
                  press_type: hold
        # If we did not hold, then continue processing as a tap
        - condition: template
          value_template: "{{ (((as_timestamp(now()) - button_start|float)*1000)|int) < hold_ms }}"
        # Wait to see if we double tap
        - wait_template: "{{ states(pico_id) == button_id|string }}"
          timeout:
            milliseconds: "{{ tap_ms }}"
        - choose:
            # Double tap actions
            - conditions: "{{ wait.completed }}"
              sequence:
                - service: system_log.write
                  data:
                    message: "{{ pico_id }} - Double tap of '{{ button_name }}'"
                    logger: pico_buttonpress
                    level: debug
                - event: pico_buttonpress
                  event_data: 
                    entity_id: "{{ pico_id }}"
                    button_pressed: "{{ button_name }}"
                    press_type: doubletap
            # Single tap actions
            - conditions: "{{ not wait.completed }}"
              sequence:
                - service: system_log.write
                  data:
                    message: "{{ pico_id }} - Single tap of '{{ button_name }}'"
                    logger: pico_buttonpress
                    level: debug
                - event: pico_buttonpress
                  event_data: 
                    entity_id: "{{ pico_id }}"
                    button_pressed: "{{ button_name }}"
                    press_type: tap
1 Like

I should note that in the my automation, the condition is looking up remote names from the variable custom component. If you were to use it , the condition would need to be updated with the names of your own Pico sensors, something like:

      condition: "{{ trigger.event.data.entity_id in ['sensor.pico_remote_1', 'sensor.pico_remote_2', 'sensor.pico_remote_3']
                      and trigger.event.data.old_state.state|int == 0 
                      and trigger.event.data.new_state.state|int != 0 }}"
1 Like

Nice I was liking the Node-Red as it was visual and know that more native is always preferred so I really appreciate the assistance with the YAML. I figured to make up a file/list with the remote names and that was what your variable.pico_remotes was pointing to. Then I use the event data to make for example a hue light automation link to the events to dim or turn on or off?

Yes, that’s correct

1 Like

This is working great! did you ever solution something for the “is circadian switch enabled?” and if so disable it. Thinking I can add a condition as part of the automation but I like the simplicity you created with a master Pico event system and didn’t want to re-invent the wheel.

I moved from the Circadian component to Adaptive Lighting, which will be finding its way into HA Core soon. It has logic that will detect when a light was manually changed, and will stop making adjustments until the light has been turned off.

But you can create other automations that listen for pico_buttonpress events to further customize the behavior. For example, I have set up a double-click of the action button to remove the manual control that I mentioned above, and re-apply the adaptive lighting.

@MizterB Any chance you could share the automation you made that takes the double-click of the action switch to remove the manual control and re-apply the adaptive lighting? I gave the automation process a go and have it built out but unable to parse the event for some reason so thinking an example would be super helpful. Thanks again for all the help

There is a lot of complexity in my button press handler right now, which is specific to my setup and I am working to simplify. I wanted a generic automation that can work for multiple pico remotes dealing with multiple adaptive switches and multiple light switches through the use of configuration variables. So I am going to share an edited snippet of what should work for you, rather than my actual automation. It assumes some hard-coded entity IDs, rather than the variables that I use.

    ################################################################################
    # AUTOMATION: pico_light_buttonhandler
    # Handler for Pico light-controlling remotes
    ################################################################################
    - alias: pico_light_on_buttonpress
      mode: single
      trigger:
        platform: event
        event_type: pico_buttonpress
      action:
        - variables:
            pico_id: "{{ trigger.event.data.entity_id }}"
            button_pressed: "{{ trigger.event.data.button_pressed }}"
            press_type: "{{ trigger.event.data.press_type }}"
            # NOTE: Configure your own entity IDs for the AL switch and corresponding light below
            adaptivelighting_id:
            light_id:
        - choose:
            # On-Tap: Turn lights on with adaptive brightness & color
            - conditions: "{{ button_pressed == 'on' and press_type == 'tap' }}"
              sequence:
                # You cannot apply both brightness and color when turning a light on from an off state.
                # Manually apply the AL brightness first.  This prevents a light from briefly going to
                # its previous brightness before the AL component takes control. This way you don't blind
                # yourself in the middle of the night.
                - service: light.turn_on
                  data:
                    entity_id: "{{ light_id }}"
                    brightness_pct: "{{ state_attr(adaptivelighting_id, 'brightness_pct') }}"
                - service: light.turn_on
                  data:
                    entity_id: "{{ light_id }}"
                    color_temp: "{{ state_attr(adaptivelighting_id, 'color_temp_mired') }}"
            # On-DoubleTap: Turn lights on at max brightness, keep color
            - conditions: "{{ button_pressed == 'on' and press_type == 'doubletap' }}"
              sequence:
                - service: light.turn_on
                  data:
                    entity_id: "{{ light_id }}"
                    brightness_pct: 100
            # Off-Tap: Turn lights off
            - conditions: "{{ button_pressed == 'off' and press_type == 'tap' }}"
              sequence:
                - service: light.turn_off
                  data:
                    entity_id: "{{ light_id }}"
            # Off-DoubleTap: Turn light on at min brightness, keep color
            - conditions: "{{ button_pressed == 'off' and press_type == 'doubletap' }}"
              sequence:
                - service: light.turn_on
                  data:
                    entity_id: "{{ light_id }}"
                    brightness_pct: 1
            # Up-Hold: Increase brightness at each interval
            - conditions: "{{ button_pressed == 'up' }}"
              sequence:
                - service: light.turn_on
                  data:
                    entity_id: "{{ light_id }}"
                    brightness_step_pct: 15
            # Down-Hold: Decrease brightness at each interval
            - conditions: "{{ button_pressed == 'down' }}"
              sequence:
                - choose:
                    # Don't allow dimming below a value of 1, which would turn off the light
                    - conditions: "{{ (1-(255 - state_attr(light_id, 'brightness')|int)/255)*100 <= 15 }}"
                      sequence:
                        - service: light.turn_on
                          data:
                            entity_id: "{{ light_id }}"
                            brightness: 1
                  default:
                    - service: light.turn_on
                      data:
                        entity_id: "{{ light_id }}"
                        brightness_step_pct: -15
            # Action-Tap: 
            - conditions: "{{ button_pressed == 'action' and press_type == 'tap' }}"
              # NOTE: This sequence has been removed as it was heavily customized to iterate through multiple lighting 'profiles'
              sequence: []
            # Action-DoubleTap: Restore adaptive lighting
            - conditions: "{{ button_pressed == 'action' and press_type == 'doubletap' }}"
              sequence:
                # Remove the light from manual control
                - service: adaptive_lighting.set_manual_control
                  data:
                    entity_id: "{{ adaptivelighting_id }}"
                    lights: "{{ light_id }}"
                    manual_control: false
2 Likes

@MizterB Awesome much thanks. I assume this is per pico remote right? I have different remotes for different rooms so figure this would be per pico to set of lights so to speak? Also assuming https://github.com/basnijholt/adaptive-lighting for the AL? I want to make the switch from Node-Red to native and get the components right until AL is natively baked in. I really appreciate all the help!

Yes on all fronts. The automation as I shared it would need to be copied for each Pico/set of lights.

I have a Lutron Caseta Pro hub and a bunch of pico remotes and hue lights. I’ve figured out how to make them turn on/off and toggle with the middle button (using the home assistant automations). However, I’m a total beginner. I’ve got node red installed, and I can import the json @MizterB has created, but I have not idea really what I’m looking at or how to apply it to my lights. Any suggestions of where someone like me could go to learn enough to be able to understand and implement this for myself? Alternatively, I’d be willing to pay for some support via web conference if someone is willing to help me get this implemented and get me started on understanding how it works.

I know you have moved on to use the native automations for your pico remotes now. But I would like to see if you could help me figure this out.

In your “Config Flow” node for your ‘msg.service_action_tap_single’ you use this json code to switch scenes.

[
    {
        "domain": "hue",
        "service": "hue_activate_scene",
        "data": {
            "group_name": "FamilyRoom Ceiling",
            "scene_name": "Bright"
        }
    },
    {
        "domain": "hue",
        "service": "hue_activate_scene",
        "data": {
            "group_name": "FamilyRoom Ceiling",
            "scene_name": "Dimmed"
        }
    },
    {
        "domain": "hue",
        "service": "hue_activate_scene",
        "data": {
            "group_name": "FamilyRoom Ceiling",
            "scene_name": "Relax"
        }
    }
]

I do not have the “Hue” integration and would like to use scenes I have setup via the “Scene Editor” in HA. Here is my code (and I’ve tried various approaches) but cannot get it to work with your sub flow.

[
    {
        "domain": "scence",
        "service": "scene.turn_on",
        "target": {
            "entity_id": "scene.my_bedroom_bright"
        }
    },
    {
        "domain": "scence",
        "service": "scene.turn_on",
        "target": {
            "entity_id": "scene.my_bedroom_relax"
        }
    },
    {
        "domain": "scence",
        "service": "scene.turn_on",
        "target": {
            "entity_id": "scene.my_bedroom_red"
        }
    }
]

Could you help me out if you get a chance?

I believe you have a typo in your domain name - should be “scene”. Additionally service should just be “turn on”.

    {
        "domain": "scene",
        "service": "turn_on",
        "target": {
            "entity_id": "scene.my_bedroom_red"
        }
    }

I am literally going to die lmao. I’m going to fix that when I get home and if it was a simple typo :exploding_head:. Thanks for reaching back out though.

I didn’t enclose the code in [ ] that was my error on top of the typo. Thank you for your help