Terrific way to use a Shelly Dimmer 2 in a thorny situation

For once I am giving back instead of taking - pay iot forward (pun intended)!

(I added a picture of the end result and the wiring diagram - in another post way towards the bottom of this thread, the below original post is how to do all the configuration.)

Elegant solution to a gnarly Shelly Dimmer 2 problem, thought it might be useful to others!

(By the way, this is 110V USA - and here, up is usually on and down is usually off - but the same concepts would work anywhere.)

Problematic requirements:

  • Keep old fashioned USA standard two-switch wall plate (as ours is custom painted)
  • Replace one of the two switches with a dimmer - but keep it looking like an old wall switch
  • No neutral available
  • No Zwave or Zigbee
  • Have to stick with WiFi (not BLE)
  • Able to integrate with HA
  • Still be able to at least turn the light on and off even if HA is dead
  • No bypass!

A very long search through the internet - for something that can be integrated reliably into Home Assistant via WiFi only with no additional hub or dongle needed resulted in only the below solution which finally works like an easy to use “dumb” dimmer switch - but seamlessly integrates behind the scenes with home automation:

Solution:

Configuration (#1-3):

  1. Ensure the switch is connected as detached as shown here in the Shelly dimmer 2 setttings:

Note regarding the above, the dual button mode should NOT be used as it has the following issues: short presses up OR down BOTH toggle the light on and off which is confusing, and even if the light is already on, a long press up will dim the light to 0% brightness FIRST and then start increasing the light level. Very annoying!

Note, Button 1 is up (on or increase brightness if held) and Button 2 is down (off or decrease brightness if held). Depending upon how you wired the switch, you can just swithc 1 and 2 in the Shelly settings so no need to take the dimmer back out of the wall to do that!).

However - to make the switch still be able to turn the light on or off even if HA is dead and while the switch is set to detached mode - go to the Shelly Dimmer 2 settings and put this in the button 1 short pressed URL (and enable it):

http://localhost/light/0?turn=on

and conversely put this in the button 2 short pressed URL (and enable that as well):

http://localhost/light/0?turn=off

Example for the button 2 short pressed off in the settings is here:

Which means that now, a short push of the switch up will still turn the switch on - and only on (even if pressed again), and a short push down will still turn it off - and only off - even though it is detached - even if Home Assistant has died!

How does that work if the dimmer has the switch in DETACHED mode? Look at the url’s entered - they are calling “localhost” so that just means the dimmer 2 is making an internal call to itself - and that still works in detached mode :slight_smile:

The only thing that is now no longer directly controlled by the physical dual pole momentary switch is the brightness level - which is handled by the following code for 2. long press up (brightening) and 3. long press down (dimming). The below code has been tested and the timings are needed (especially the delay within each loop) for proper operation:

  1. Home Assistant YAML code for long press up (brightening the light):

Given:

  • The up position switch entity_id in Home Assistant is: binary_sensor.den_shelly_dimmer_2_channel_2_input (replace that with the name of yours)
  • The Dimmer 2 is integrated into Home Assistant as a light (in the Shelly Dimmer 2 settings), it’s Home Assistant entity_id is: light.den_shelly_dimmer_2 (replace that with the name of yours)

(Also note, this has logic that first turns the light on without specifying the brightness, which will turn the light on at the previous brightness it already had, to then increase the brightness from there, rather than from 0% (much better and expected user experience).)

Then, this is the code:

alias: Den Shelly Dimmer 2 Long Press Up - Detached Momentary Switch
description: >-
  This automation has to use conditions only within the actions as two different
  condtions need to be met for each of two different actions. When a dual pole
  momentary switch is held in the up position (the position to turn the light
  on) for more than 250 millesconds (1/4 of a second), if the light is off first
  turn it on, and then as long as the button is still being held up, brighten
  the light by 10% every 250 milleseconds (1/4 of a second).
trigger:
  - platform: state
    entity_id:
      - binary_sensor.den_shelly_dimmer_2_channel_2_input
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 0.25
condition: []
action:
  - repeat:
      while:
        - condition: state
          entity_id: light.den_shelly_dimmer_2
          state: "off"
      sequence:
        - service: light.turn_on
          data: {}
          target:
            entity_id: light.den_shelly_dimmer_2
  - repeat:
      while:
        - condition: state
          entity_id: binary_sensor.den_shelly_dimmer_2_channel_2_input
          state: "on"
      sequence:
        - service: light.turn_on
          data:
            brightness_step: 10
            transition: 1
          target:
            entity_id: light.den_shelly_dimmer_2
        - delay:
            hours: 0
            minutes: 0
            seconds: 0
            milliseconds: 250
mode: single
  1. Home Assistant YAML code for long press down (dimming the light - only if it is on) -
    Given:
  • The down position switch Home Assistant entity_id is: binary_sensor.den_shelly_dimmer_2_channel_1_input (replace that with the name of yours)

Then, this is the code:

alias: Den Shelly Dimmer 2 Long Press Down - Detached Momentary Switch
description: >-
  When a dual pole momentary switch is held in the down position (the position
  to turn the light off) for more than 250 millesconds (1/4 of a second) - only
  if the light is on - while the switch is still being presssed, dim the light
  by 10% every 250 milleseconds (1/4 of a second).
trigger:
  - platform: state
    entity_id:
      - binary_sensor.den_shelly_dimmer_2_channel_1_input
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 0.25
condition:
  - condition: state
    entity_id: light.den_shelly_dimmer_2
    state: "on"
action:
  - repeat:
      while:
        - condition: state
          entity_id: binary_sensor.den_shelly_dimmer_2_channel_1_input
          state: "on"
      sequence:
        - service: light.turn_on
          data:
            brightness_step: -10
            transition: 1
          target:
            entity_id: light.den_shelly_dimmer_2
        - delay:
            hours: 0
            minutes: 0
            seconds: 0
            milliseconds: 250
mode: single

Tweaked to perfection by a home automation fanatic, increasing WAF from 0% to 100%. :slightly_smiling_face:

I have to correct the above to the below. Any issue with the home automation - decreases it by at least 99%. Any good thing with home automation - increases it by about 0.001 % lol

Tweaked to perfection by a home automation fanatic, increasing WAF from 32% to 32.001%. :- :joy:

8 Likes

Very Interesting approach.

This was super useful, I created an account just to say thanks!

1 Like

Definitely helpful! Thanks for taking the time to post. Mad that I “assumed” Shelly dimmer would be able to integrate with existing wall switches.

@KruseLuds Any suggestions on where to purchase the Leviton switch? Feel like $36 for a dumb switch is pretty pricey on Amazon

That kind of switch is actually pretty expensive - I don’t know why. However, you will see when you get it - it is built to last forever - it is way overbuilt - almost as though it is for an industrial setting (but still is the correct size) -

1 Like

Here in Australia I used these switches:
https://www.clipsal.com/products/power-points-switches/pro-series/switch-mechanism-3-position-bell-press-return-10a-250v-p49mbpr?itemno=P49MBPR-XW&tab-document-1=0

I have just started my journey with these little treasures and am wondering when you actually import them into HA?

Do you do the initial config with ON/OFF url confirming which way the switch goes?
OR
It doesn’t matter?

Thanks

I have combined the script for the shelly 2 dimmer control into one single automation, which makes the HA setup much cleaner. I am intending to make a blueprint for it eventually containing all the docs, etc and credit of course :slight_smile: in the meantime here’s my update:

alias: dining room light
description: >-
  Turn on/off then increase/decrease the brightness of the light using shelly
  dimmer inputs
trigger:
  - platform: state
    entity_id:
      - binary_sensor.dining_room_light_channel_1_input
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 0.25
  - platform: state
    entity_id:
      - binary_sensor.dining_room_light_channel_2_input
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 1
condition: []
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: binary_sensor.dining_room_light_channel_1_input
            state: "on"
        sequence:
          - repeat:
              while:
                - condition: state
                  entity_id: light.dining_room_light
                  state: "off"
              sequence:
                - service: light.turn_on
                  data: {}
                  target:
                    entity_id: light.dining_room_light
            alias: Turn on light
          - alias: Increase light
            repeat:
              while:
                - condition: state
                  entity_id: binary_sensor.dining_room_light_channel_1_input
                  state: "on"
              sequence:
                - service: light.turn_on
                  data:
                    brightness_step: 10
                    transition: 1
                  target:
                    entity_id: light.dining_room_light
                - delay:
                    hours: 0
                    minutes: 0
                    seconds: 0
                    milliseconds: 250
      - conditions:
          - condition: state
            entity_id: binary_sensor.dining_room_light_channel_2_input
            state: "on"
        sequence:
          - repeat:
              while:
                - condition: state
                  entity_id: binary_sensor.dining_room_light_channel_2_input
                  state: "on"
              sequence:
                - service: light.turn_on
                  data:
                    brightness_step: -10
                    transition: 1
                  target:
                    entity_id: light.dining_room_light
                - delay:
                    hours: 0
                    minutes: 0
                    seconds: 0
                    milliseconds: 250
    default:
      - stop: Nothing to do
mode: single

4 Likes

This is great, but say I have ten (10) dimmers, is there a way to pass the name of the light switch to the script so that I don’t have to have 10 versions of the same script and just use the variable?

Yes… you are in luck - it took me a while because it is documented very poorly if anywhere… but how I figured it out is shown below.

I have not done whaty you are doing as I have it only for one dimmer, but as an example I do have many autromations passing parameters to the same script -

So that you understand my paradigm in my setup my crappy motion detectors (that is why I do it this way to overcome that) - call a script to (re)start a related timer. The Script does nothing if the automation is disabled otherwise it starts the timer with a duration that I have set by a slider in my dashboard. All of those entities are passed to the script which is called from all over the place (This way I was able to remove a lot of redundant code which is what you are trying to do.) When the timer (re)starts it turns the light on (if not already on) and when the timer finishes it turns the light off.

So, for a specific light, this is when motion is sensed - (note the action section which calls a script with parameters):

alias: Den Motion Detected (Lamp By Closet Automation)
description: ""
trigger:
  - type: motion
    platform: device
    device_id: 5ef8f43f23c1d09910584c8c6a3cb29c
    entity_id: binary_sensor.den_motion_sensor_motion
    domain: binary_sensor
condition: []
action:
  - service: script.motion_detected
    data:
      enablement_input_selector_entity: input_select.den_automation_lamp_by_closet_is
      timer_duration_entity: input_number.den_adjust_couch_lamp_by_closet_timer
      timer_entity: timer.den_couch_lamp_by_closet_timer
mode: parallel
max: 1000

And here is the script that it calls. I call this from all over the place.

alias: Motion Detected
sequence:
  - condition: template
    value_template: "{{ is_state(enablement_input_selector_entity,'Enabled') }}"
  - service: timer.start
    data:
      duration: "{{ (states(timer_duration_entity)|int*60) }}"
    target:
      entity_id: "{{ timer_entity }}"
mode: parallel
max: 1000
icon: mdi:run-fast

I got this code working now for multiple lights. Simply add your appropriate binary_sensor(s) and the rest just works.

For the below code to work the way I wanted, I have my UP button set as Channel 1 and my DOWN button set as Channel 2.

alias: Shelly Dimming
description: This allows the shelly to dim the lights
# I have Channel 1 set as UP and Channel 2 and DOWN
trigger:
# Push button up for 1/4 second to brighten
  - platform: state
    entity_id:
      - binary_sensor.waiting_channel_1_input
      - binary_sensor.hallway_channel_1_input
      - binary_sensor.mud_room_channel_1_input
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 0.25
# Push button down for 1 second to dim
  - platform: state
    entity_id:
      - binary_sensor.waiting_channel_2_input
      - binary_sensor.hallway_channel_2_input
      - binary_sensor.mud_room_channel_2_input
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 1
condition: []
action:
# Set a variable for the light we are going to adjust
  - variables:
      light_entity_id: >-
        light.{{
        trigger.to_state.object_id|replace('_channel_1_input','')|replace('_channel_2_input','')
        }}
# Before we do anything need to turn the light on if it is off
  - alias: Turn on light
    repeat:
      while:
        - condition: template
          value_template: >-
            {{ is_state('light.' ~
            trigger.to_state.object_id|replace('_channel_1_input','')|replace('_channel_2_input',''),
            'off') }}
      sequence:
        - service: light.turn_on
          data: {}
          target:
            entity_id: "{{ light_entity_id }}"
  - choose:
# Test to check we are holding the up button
      - conditions:
          - condition: template
            value_template: "{{ ('channel_1' in trigger.entity_id) == true }}"
          - condition: template
            value_template: "{{ is_state (trigger.entity_id, 'on') }}"
        sequence:
          - alias: Increase light
            repeat:
              while: # Whilst holding the up button
                - condition: template
                  value_template: "{{ is_state (trigger.entity_id, 'on') }}"
              sequence:
                - service: light.turn_on
                  data:
                    brightness_step: 10
                    transition: 1
                  target:
                    entity_id: "{{ light_entity_id }}"
                - delay:
                    hours: 0
                    minutes: 0
                    seconds: 0
                    milliseconds: 250
# Test to check we are holding the down button
      - conditions:
          - condition: template
            value_template: "{{ ('channel_2' in trigger.entity_id) == true }}"
          - condition: template
            value_template: "{{ is_state (trigger.entity_id, 'on') }}"
        sequence:
          - repeat:
              while: # Whilst holding the down button
                - condition: template
                  value_template: "{{ is_state (trigger.entity_id, 'on') }}"
              sequence:
                - service: light.turn_on
                  data:
                    brightness_step: -10
                    transition: 1
                  target:
                    entity_id: "{{ light_entity_id }}"
                - delay:
                    hours: 0
                    minutes: 0
                    seconds: 0
                    milliseconds: 250
# Otherwise do nothing.
    default:
      - stop: Nothing to do
mode: single

1 Like

Best thing ever; so glad you posted this solution mate!

I’m not sure I get why some of you decided to set the dim down conditions to 1 second as opposed to 1/4, nor how you turn off the lights except by diming all the way down?

I have a Circadian lighting custom component that I use to modulate brightness and color temp depending on the time of day that syncs all my smart lights. So in my case, the trigger of manually diming will need to override this, which is not hard to do through a binary toggle.

I will try to add a off function with a push of a button for channel 2 lower than the condition to trigger which resets the Circadian Lighting mechanism.

This post was a godsend and quite possibly saved my marriage, cheers!

With the OFF, if you look at the earlier posts you will see that is simply part of the switch configuration.

Following the set up for the URLs a quick press up turns the light on and a quick press down turns it off. This is also in the event that HA is not working properly you can still turn the light on and off.

With the timings, especially the dimming, yeah I wasn’t sure about the 1 second delay, but I left it that way till I check the WAF and see what the verdict is. The best thing about HA is you can simply change the value to something that works for you.

1 Like

Just the short press down and release will turnjh it off, then a short press up will turn it on - to the brightness it had before

1 Like

Thanks for the clarifications, that trick is neat.

Unfortunately, my implementation is different: I am using a Shelly i3.

That switch doesn’t have a binary sensor when set to momentary switch.
So I hacked it by configuring it as a Toggle Switch wired to a physical momentary switch.
When configured this way, a binary sensor is available and triggered when I press the physical switch, which works with this automation.

However, the URL actions are now limited to Switch On or Off which doesn’t seem to play nice with this idea unfortunately.

Using a Dimmer 2 just for the detached switch seemed a waste to me as the i3 was pretty much all I needed. If the WAF degrades too much, I might have to reconsider.

You aren’t able to use long press to incrementally change brightness? Bummer!

Nope the brightness change works fine :slight_smile: It’s the URL implementation to switch on/off that can’t be implemented. So long pressing either button will turn the lights on, but the only way to switch off at the moment is to dim all the way down.

If acceptable maybe increase the speed at which the lights dim or brighten (or by larger increments like 25% instead of 10% each time…)?

Sorry, no, you miht be able to find it at Home Depot or something like that but thyese levitons wil outlast your house and you and me. They are built to last forever. Built like a tank.

This is the end result. Switch on the left is the dimmer! (For people who have the direct link to this post, scroll up for my original post and all the configuration details.)

and the wiring (actually two shelly’s behind this faceplate (a Shelly Dimmer 2 and a Shelly 1L) for two different things):