This Time Self-Hosted
dark mode light mode Search

Home Assistant Tales: The Bathroom Lights

I have already mentioned when talking about lights and buttons, that we have an unconventional bathroom lights setup. It also comes with quite a bit of unconventional automation to go with it, and I thought it would be an interesting topic for a write up, given that a lot of my other smart home posts end up attracting quite a bit of a readership.

Let me start with a bit of logistics. This is a two bedrooms, two bathrooms flat — but realistically, the only bathroom that is in daily use is the ensuite. The other bathroom is mostly used exclusively to dry clothes and to store bathroom necessities (since the ensuite is much smaller.)

The ensuite has a walk-in shower, and three spotlights running along the middle of the ceiling, one of them being on top of the shower. Like every other light in this flat (and most of the other flats me and my wife visited in the area), all the lights are GU-10 spotlights — originally all LEDs, between 4W and 7W each. The lights were originally only controlled by a wall switch wired in some… confusing manner — I know that because I had it checked out considering replacing it with a smart switch as the one installed is very clicky, and we kept waking each other up when using the bathroom overnight. The confusing wiring meant we decided not to do that at all.

Instead, we took a page from Big Clive and the suggestion of keeping a low-brightness dusk throughout the day, instead of using bright lights overnight — so I ordered three Philips Hue GU10 spots (because the Philips models are known to handle the low-brightness better than the IKEA ones), and set those up, together with a physical button (at first a Flic, then an Aqaria when I switched the lights from the Hue Bridge to Home Assistant.)

Having three, individually-dimmable spots in the bathroom turned out to allow for a lot of useful flexibility: first of all, overnight we only need the shower spot set to 1% — it’s not bright at all, but it’s plenty of lights to come in, use the toilet, and wash your hands. It even works great during the day, so it turns out that most of the day, the light stays exactly the same, and we don’t turn on the “normal” light at all. While this may sound pointless to calculate, the “additional” energy used by the always-on light (and the overall consumption of the Zigbee stack) is well recovered by not turning on the lights when using the toilet during the day. Plus, you know, we stopped waking each other up overnight, which was the whole point we needed. I have considered putting some movement sensor and just turn on the 1% light when we would be walking close to the bathroom, but it felt too finicky with extra batteries to use.

But it didn’t stop there. Turns out that most of the time, we don’t need the full on brightness, even if we need some light in the bathroom — for instance when we need to use the mirror, brush our teeth, or generally getting ready. So the default “on” state for the bathroom light is a pleasant 40% maximum brightness, while a different scene is set up for when you do need the full brightness, that is when we need to clean the bathroom. On a more indulgent note — having the shower spot at full brightness, while keeping the other two off altogether, is something that we find quite enjoyable.

You can see from this that we clearly needed to have separate scene settings for the four modes: Night, Day, Bright, and Shower. And eventually, we needed a fifth “scene” of off — I say eventually, because many, many months passed before both me and my wife left the apartment at the same time, thanks to the whole pandemic situation and the fact that I’m considered at risk from diabetes. To choose between these, I originally set up an input select helper with the five entries, and an automation that selects the scene to activate based on said helper:

alias: Bathroom Lights Automation
description: ''
trigger:
  - platform: state
    entity_id: input_select.bathroom_lights
action:
  - service: scene.turn_on
    target:
      entity_id: >-
        {% if is_state("input_select.bathroom_lights", "Day") %}
        scene.bathroom_day {% elif is_state("input_select.bathroom_lights",
        "Night") %} scene.bathroom_night {% elif
        is_state("input_select.bathroom_lights", "Bright") %}
        scene.bathroom_bright {% elif is_state("input_select.bathroom_lights",
        "Shower") %} scene.bathroom_shower {% elif
        is_state("input_select.bathroom_lights", "Off") %} scene.bathroom_off {%
        endif %}
mode: restart

This was a great starting point, but it had a few drawbacks. For once, it doesn't work with voice assistants (Google Assistant and Alexa) as they don't know how to change an input select. But also it seemed to create conflicts with the scene settings when we would leave the apartment, and sometimes we found we left the light on for a couple of hours, which is less than ideal. So I thought of a solution in the form of a phone notification if the light stayed on for longer than twenty minutes — which is not a short time, but it's a reasonable one for us to keep the light on when getting ready, particularly when taking turns. Unfortunately this kept triggering while we were taking showers, so I needed a little more finesse for it: thanks to the CGG1 sensor in the bathroom (which I originally put there to see if we had a build-up of steam), I can tell when we're taking a shower by checking for humidity staying over 65% for more than a couple of minutes (it's a very dry flat), and in that case not send the notification.

In addition to reminding us that the light is still on, the notification has a "Turn Off" action — which basically goes ahead to turn off the light, so that we don't have to open the app or talk to any of the voice assistants: it just works from the notification UI.

I am considering packaging this up in a blueprint — mostly because now that we changed the spots in the corridor, where lights are also turned on for short periods of time at once, it would be nice to have those notifications as well. But right now it does not look like the blueprint would have an easy way to configure optional parameters, so I have not done much about it. It also doesn't help that I haven't merged the notification and action into a single automation, which means they can't easily be duplicated (yet.)

alias: 'Bathroom Lights Mobile: Send Reminder'
description: ''
trigger:
  - platform: state
    entity_id: switch.bathroom_lights
    for: '00:20:00'
    to: 'on'
condition:
  - condition: state
    entity_id: binary_sensor.bathroom_showering
    state: 'off'
action:
  - service: notify.all_devices
    data:
      message: Did you forget the Bathroom lights on?
      data:
        actions:
          - action: turn_off_bathroom_light
            title: Turn Off
mode: single
alias: 'Bathroom Lights Mobile: Turn Off Action'
description: ''
trigger:
  - platform: event
    event_type: mobile_app_notification_action
    event_data:
      action: turn_off_bathroom_light
condition: []
action:
  - service: switch.turn_off
    target:
      entity_id: switch.bathroom_lights
mode: single

You may notice here something a bit confusing: what is this switch.bathroom_lights, if earlier I said I set up an input select for this? Well, the answer is that to make a lot of things easier, to work with the voice assistants, and to actually work together with the scenes we use when we leave the apartment or come back, the easiest option is to have a template switch in addition to the input select.

The template switch is configured to represent the state of the input select into a simpler boolean on/off view, keeping in mind that, if we're home, the "off" state should be the 1% "Night" scene, while if we're not at home, it should be the "Off" scene — the "home" question being another helper, a boolean input that we manually trigger when we leave the flat, and disarm when we come back.

switch:
  - platform: template
    switches:
      bathroom_lights:
        friendly_name: "Bathroom Lights"
        unique_id: bathroom_lights_switch
        value_template: >-
          {% if is_state("input_select.bathroom_lights", "Night") %}
            off
          {% elif is_state("input_select.bathroom_lights", "Off") %}
            off
          {% else %}
            on
          {% endif %}
        turn_on:
          service: input_select.select_option
          target:
            entity_id: input_select.bathroom_lights
          data:
            option: Day
        turn_off:
          service: input_select.select_option
          target:
            entity_id: input_select.bathroom_lights
          data:
            option: >-
              {% if is_state("input_boolean.home", "on") %}
                Night
              {% else %}
                Off
              {% endif %}
        icon_template: >-
          {% if is_state("switch.bathroom_lights", "on") %}
            mdi:lightbulb-group
          {% else %}
            mdi:lightbulb-group-outline
          {% endif %}

This means that instead of complicating the automation (like I did originally for a few months) to deal with the input select when turning off the lights, I can now just turn off the switch and let the template handle whatever needs to be done. Also, since it's a switch, it can be exposed to Google Assistant and Alexa via Home Assistant Cloud, and they both respond to «Turn off the bathroom lights» if we forget them on.

All of this together is quite the quality of life improvement, and even a bit indulgent. It is the kind of thing you don't really need and that it would be wasteful to set up just for the sake of it in isolation — but it is somethign that, once you start having a more automated smart home, you're generally glad to have available.

There's then another bonus — on the wall by the door inside the bathroom we have a Glade Sense & Spray freshener, that uses a light sensor to identify motion. This used to be triggered every time we turned on the light, but because of the dusk, that's not happening as often anymore. Not a big loss as the main point of it is that it comes with a button that allows you to fire it on demand… but why not having it automated?

alias: Spray Freshener in Bathroom
sequence:
  - service: scene.create
    data:
      scene_id: tmpscene_bathroom_door
      snapshot_entities: light.bathroom_light_door
  - type: turn_on
    device_id: # [omissis]
    entity_id: light.bathroom_light_door
    domain: light
    brightness_pct: 100
  - delay:
      hours: 0
      minutes: 0
      seconds: 1
      milliseconds: 500
  - scene: scene.tmpscene_bathroom_door
mode: single
icon: mdi:spray

As it turns out, "flashing" the door light once is enough for it to trigger, and that means we can ask the voice assistants for it, as well as having it on a button on the dashboard, if we want to. Neat. Pointless, but neat.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.