Lutron Caseta Pico to ZHA Zigbee Dimmer Control

This blueprint is based on stephack’s Lutron Caseta Pico Blueprint and requires ZHA Toolkit in order to work. ZHA Toolkit can be found through HACS as one of the repositories in the default list. Thank you to both for creating great integrations!

ZHA Group Update: This blueprint now supports ZHA groups. If you want to control multiple bulbs at the same time, you can select a main bulb, the group’s entity ID, the group number, and the group entity ID. If you don’t enter a group entity ID, then the blueprint will ignore the group control part of the blueprint and just control a single light. The Groups supported are the groups found in settings → devices and services → configure (on ZHA) → groups. This blueprint will use the native Zigbee group commands to keep the lights in sync and to reduce the total number of commands needed. I have this bluepint set to control all of the Zigbee bulbs in my living room in parallel with a native pico to caseta dimmer, and the Zigbee lights act as if they are connected to the same control sequence. Even when using a group, an entity ID of a single light in the group is used to sync the brightness at the end of a dimming sequence as some bulb manufacturers have slight variations on how quickly they will start and stop dimming.

I wanted to be able to use a pico remote to control some of my Zigbee bulbs, but I didn’t want them to act differently from my Caseta dimmers. This blueprint uses cluster commands through ZHA Toolkit to stop in-progress dimming and to read back the state in order to mimic the smooth dimming seen in Caseta dimmers. I left the middle button alone. You can set a favorite brightness like on the original remote or you can use it for any function you like.

In the Caseta app, you can unpair the pico remote from your dimmer by tapping on it → going to edit device → select devices → uncheck the original dimmer and save.

I also modified joshcarter’s 3D printed Pico wall mount for a more solid feel and posted it here.

You should be able to import the blueprint through either clicking on the button below or by copying and pasting the blueprint into a .yaml file in your blueprint folder.

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

blueprint:
  name: ZHA - Pico Config
  description: "This is for the 5 button picos that have the following model:\n\n
    PJ2-3BRL-GXX-X01 (Pico3ButtonRaiseLower)\n\nSelect the pico and light to use below"
  domain: automation
  input:
    pico_remote:
      name: Pico Remote
      description: 'Select the pico remote to configure:'
      selector:
        device:
          model: PJ2-3BRL-GXX-X01 (Pico3ButtonRaiseLower)
          multiple: false
    light:
      name: Zigbee Light
      description: "Select the light to control.\nIf using a group, select the main light for matching brightness:"
      selector:
        entity:
          multiple: false
    group_entity:
      name: Zigbee Group Entity ID
      description: "Optional - Entity ID for the ZHA group you wish to control"
      default: []
      selector:
        entity:
          multiple: false
    zha_group:
      name: ZHA Group Number
      description: "Optional - If using a group, set this to the matching group number from the ZHA interface. Otherwise, leave blank"
      default: []
    dimming_speed:
      name: Dimming Speed
      description: 'Input the dimming speed to go from 0 to 100%'
      default: 5
    turn_on_speed:
      name: Turn On Speed
      description: 'Input the time to turn on the light'
      default: 0
    turn_off_speed:
      name: Turn Off Speed
      description: 'Input the time to turn off the light'
      default: 2
    auto_mode:
      name: Automation Mode
      description: Mode that automation runs in (single,  restart, queued, parallel).
      default: restart
      selector:
        select:
          options:
          - single
          - restart
          - queued
          - parallel
          multiple: false
          custom_value: false
    mode_max:
      name: Mode Max (ignored by Single and Restart Modes)
      description: Maximum number of runs that can be executed or queued at a time.
      default: 10
      selector:
        number:
          min: 1.0
          max: 15.0
          mode: slider
          step: 1.0
    middle_stop:
      name: Middle (Fav) Button Pressed
      description: Execute when MIDDLE button is PRESSED
      default: []
      selector:
        action: {}
    middle_stop_release:
      name: Middle (Fav) Button Released
      description: Execute when MIDDLE button is RELEASED
      default: []
      selector:
        action: {}
variables:
  light_entity: !input light
  dimming_speed: !input dimming_speed
  zha_group: !input zha_group
  group_entity: !input group_entity
  turn_off_speed: !input turn_off_speed
trigger:
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: press
  subtype: 'on'
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: press
  subtype: raise
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: press
  subtype: stop
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: press
  subtype: lower
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: press
  subtype: 'off'
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: release
  subtype: 'on'
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: release
  subtype: raise
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: release
  subtype: stop
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: release
  subtype: lower
- platform: device
  device_id: !input pico_remote
  domain: lutron_caseta
  type: release
  subtype: 'off'
condition: []
action:
- choose:
  - conditions: '{{ trigger.event.data.action == "press" }}'
    sequence:
    - choose:
      - conditions: '{{ trigger.event.data.button_number == 5 }}' #up_raise
        sequence: 
          - if: '{{ zha_group != []}}'
            then:
              - service: zha.issue_zigbee_group_command
                data:
                  cluster_id: 8
                  command: 3
                  group: !input zha_group
            else:
              - service: zha_toolkit.execute
                data:
                  ieee: !input light
                  cluster: 8
                  cmd: 3
                  command: zcl_cmd
          - service: zha_toolkit.attr_read
            data:
              cluster: 8
              ieee: !input light
              attribute: 0
              state_id: >
                {% if zha_group != [] %}
                  {{group_entity}}
                {% else %}
                  {{light_entity}}
                {% endif %}
              state_attr: brightness
          - service: light.turn_on
            data:
              brightness: 255
              transition: >-
                {% if zha_group != [] %}
                  {{(((255-(state_attr(group_entity, 'brightness') | int(0)))/255)*(dimming_speed|float(5)-0.1))+0.1}}
                {% else %}
                  {{(((255-(state_attr(light_entity, 'brightness') | int(0)))/255)*(dimming_speed|float(5)-0.1))+0.1}}
                {% endif %}
            target:
              entity_id: >
                {% if zha_group != [] %}
                  {{group_entity}}
                {% else %}
                  {{light_entity}}
                {% endif %}
      - conditions: '{{ trigger.event.data.button_number == 3 }}'
        sequence: !input middle_stop
      - conditions: '{{ trigger.event.data.button_number == 6 }}' #down_lower
        sequence: 
          - if: '{{ zha_group != []}}'
            then:
              - service: zha.issue_zigbee_group_command
                data:
                  cluster_id: 8
                  command: 3
                  group: !input zha_group
            else:
              - service: zha_toolkit.execute
                data:
                  ieee: !input light
                  cluster: 8
                  cmd: 3
                  command: zcl_cmd
          - service: zha_toolkit.attr_read
            data:
              cluster: 8
              ieee: !input light
              attribute: 0
              state_id: >
                {% if zha_group != [] %}
                  {{group_entity}}
                {% else %}
                  {{light_entity}}
                {% endif %}
              state_attr: brightness
          - if:
              - condition: not
                conditions: >
                  {% if zha_group != [] %}
                    {{is_state(group_entity, 'off')}}
                  {% else %}
                    {{is_state(light_entity, 'off')}}
                  {% endif %}
            then:
              - service: light.turn_on
                data:
                  brightness: 4
                  transition: >-
                    {% if zha_group != [] %}
                      {{(((state_attr(group_entity, 'brightness') | int(0))/255)*(dimming_speed|float(5)-0.1))+0.1}}
                    {% else %}
                      {{(((state_attr(light_entity, 'brightness') | int(0))/255)*(dimming_speed|float(5)-0.1))+0.1}}
                    {% endif %}
                target:
                  entity_id: >
                    {% if zha_group != [] %}
                      {{group_entity}}
                    {% else %}
                      {{light_entity}}
                    {% endif %}
  - conditions: '{{ trigger.event.data.action == "release" }}'
    sequence:
    - choose:
      - conditions: '{{ trigger.event.data.button_number == 2 }}' # top_on_release
        sequence:
          - if: '{{ zha_group != []}}'
            then:
              - service: zha.issue_zigbee_group_command
                data:
                  cluster_id: 8
                  command: 3
                  group: !input zha_group
            else: # Not using a group
              - service: zha_toolkit.execute
                data:
                  ieee: !input light
                  cluster: 8
                  cmd: 3
                  command: zcl_cmd
          - service: light.turn_on
            data:
              brightness: 255
              transition: !input turn_on_speed
            target:
              entity_id: >
                {% if zha_group != [] %}
                  {{group_entity}}
                {% else %}
                  {{light_entity}}
                {% endif %}
      - conditions: '{{ trigger.event.data.button_number == 3 }}'
        sequence: !input middle_stop_release
      - conditions: '{{ trigger.event.data.button_number == 6 or trigger.event.data.button_number == 5 }}' # down_lower_release or up_raise_release
        sequence:
          - if:
              - alias: "Test for off"
                condition: template
                value_template: >
                  {% if zha_group != [] %}
                    {{is_state(group_entity, 'on')}}
                  {% else %}
                    {{is_state(light_entity, 'on')}}
                  {% endif %}
            then:
              - if: '{{ zha_group != []}}'
                then:
                  - service: zha.issue_zigbee_group_command
                    data:
                      cluster_id: 8
                      command: 3
                      group: !input zha_group
                else:
                  - service: zha_toolkit.execute
                    data:
                      ieee: !input light
                      cluster: 8
                      cmd: 3
                      command: zcl_cmd
              - service: zha_toolkit.attr_read
                data:
                  cluster: 8
                  ieee: !input light
                  attribute: 0
                  state_id: >
                    {% if zha_group != [] %}
                      {{group_entity}}
                    {% else %}
                      {{light_entity}}
                    {% endif %}
                  state_attr: brightness
              - if: '{{ zha_group != []}}'
                then:
                  - service: light.turn_on
                    data:
                      brightness: >
                        {% if zha_group != [] %}
                          {{state_attr(group_entity, 'brightness')}}
                        {% else %}
                          {{state_attr(light_entity, 'brightness')}}
                        {% endif %}
                    target:
                      entity_id: !input group_entity
      - conditions: '{{ trigger.event.data.button_number == 4 }}' # bottom_off_release
        sequence:
          - if: '{{ zha_group != []}}'
            then:
              - service: zha.issue_zigbee_group_command
                data:
                  cluster_id: 8
                  command: 3
                  group: !input zha_group
            else: # Not using a group
              - service: zha_toolkit.execute
                data:
                  ieee: !input light
                  cluster: 8
                  cmd: 3
                  command: zcl_cmd
          - service: light.turn_on
            data:
              brightness: 1
              transition: !input turn_off_speed
            target:
              entity_id: >
                {% if zha_group != [] %}
                  {{group_entity}}
                {% else %}
                  {{light_entity}}
                {% endif %}
          - if: '{{ (turn_off_speed - 0.2) > 0 }}'
            then:
              - delay:
                  seconds: '{{ turn_off_speed - 0.2 }}'
          - service: light.turn_off
            target:
              entity_id: >
                {% if zha_group != [] %}
                  {{group_entity}}
                {% else %}
                  {{light_entity}}
                {% endif %}
  default: []
mode: !input auto_mode
max: !input mode_max
2 Likes

This is great! Does it work for z2mqtt also? And will it work for multiple lights? I see the light field only has room for a single light?

No. It needs ZHA Toolkit.

I created a version that uses ZHA groups to controll all of the lights in a group. I was hoping to be able to find a way to get the group’s ID from the entity id, but I haven’t had any luck there yet. I can post that as well soon. It works for groups and single lights depending on what information is filled out.

Jerrm is correct that it only works with ZHA and ZHA Toolkit.

I tried it out with one of my rooms (Hue lights via the Hue hub plus Pico to control) just to see what would happen. It dims/brightens to the min/max setting with no way of stopping in between. I also get an error from HA saying there is information missing to run the automation. Thanks for making this. I might have to try ZHA just so I can use this.

Unfortunately for other integrations, this blueprint relies heavily on the Zigbee stop cluster command for dimming and the read command for updating the state of the bulb, which is implemented through the ZHA Toolkit zha_toolkit.execute command. Home Assistant doesn’t seem to have equivalent commands that would be universally available. Integrations like ControllerX approximate this by looping a dimming cycle, but I find the transition to be a bit more rough as it sends a bunch of Zigbee commands one after the other. This blueprint works by telling the entity to dim to the minimum brightness, but in the 5 second min to max brightness time, you can stop the transition and read back the brightness at any time by releasing the button. I’m not sure if the hue integration has cluster commands exposed, but I know that a similar effect could be gotten through other Zigbee integrations if a different method for calling the stop cluster command were to be implemented. (Cluster 8 command 3)

ZHA Group Update: This blueprint now supports ZHA groups. If you want to control multiple bulbs at the same time, you can select a main bulb in the group’s entity ID, the group number, and the group entity ID. If you don’t enter a group entity ID, then the blueprint will ignore the group control part of the blueprint and just control a single light. The Groups supported are the groups found in settings → devices and services → configure (on ZHA) → groups. This blueprint will use the native Zigbee group commands to keep the lights in sync and to reduce the total number of commands needed. I have this bluepint set to control all of the Zigbee bulbs in my living room in parallel with a native pico to caseta dimmer, and the Zigbee lights act as if they are connected to the same control sequence. Even when using a group, an entity ID of a single light in the group is used to sync the brightness at the end of a dimming sequence as some bulb manufacturers have slight variations on how quickly they will start and stop dimming.

Quick update: when using a group, the frontend will now have all of the lights in the group update their brightness at the same time. Previously, only the main light’s brightness would be read back and the rest of the lights would get their brightness updated once the light brightness was written back causing a delay.

One issue that I noticed is that Sylvania Smart+ bulbs seem to restart a turn on at 0% brightness after a turn off command gets interrupted by a turn on command. The correct behavior to match Caseta dimmers would be to start turning on from the current brightness. This issue isn’t present on my Hue, Ikea, or Cree bulbs.

One more update: The Sylvania Smart+ bulb issue is now fixed, and now if you press the dimming buttons while the switch is in the middle of turning on or off, the dimmer will work the same way that a standard caseta dimmer works by stopping the turn off/on transition and continuing dimming from the current brightness.