How to create a smart bathroom lighting system with Home assistant and Node-Red

Video

Below, you will find the video tutorial if you want to follow the step-by-step guide.

Introduction

Have you ever woken up late and, when taking your shower, wanted to know exactly how much time has passed? Of course, you can use a watch, but with this (very simple) automation, you will have a different, much cooler and more modern way to do it. In this article, we will build step by step, using Home Assistant and Node-Red, an automation using only simple Node-Red blocks. We will start with the lighting control, then we will add a notification to alert you if the light has been on for too long.

Objective

In this section, I will show you what we are going to build. Below is a simple diagram illustrating the overall behavior.

Figure 1 diagram

The first step is to check whether the light is on. If not, nothing happens. Otherwise, we turn on a white light (maximum brightness, 5000K). Then, we detect whether someone is taking a shower. For this, you can use a presence sensor, but in my case I will use a humidity sensor. If you were considering buying a presence sensor just to detect showers, keep in mind that it is not necessary.

Next, the automation will trigger light flashes in different colors every 5 minutes. After 3 flashes, if the light is still on, it likely means someone forgot to turn it off. In that case, a notification will be sent to your phone. This notification will include actions such as turning off the light remotely, which is useful when you are not at home.

With this automation, you will have a visual and practical way to track your shower duration and avoid forgetting to turn off the light.

Lighting control

In my case, I use an Ikea button running with Zigbee and Zigbee2mqtt. It is integrated into the automation so that when pressed, it can either trigger a normal lighting mode (white light, maximum brightness) or a dimmed light at night to avoid glare (which is more comfortable when waking up during the night to go to the bathroom):

Figure 2 Button

To find the button actions, you can use MQTT Explorer to identify the topic and associated action, then configure them in the node as shown below.

Figure 3 MqttTopic

If the light is already on, pressing the button again will simply turn it off. Once this logic is set up, we can move on to the shower detection part.

Shower detection

In this section, we will handle shower detection. As mentioned earlier, if you have a presence sensor you can skip this step. With a humidity sensor, we will use the derivative of the value to detect rapid changes caused by water vapor in the bathroom.

Figure 4 Derivative sensor

You can create this derivative in “Settings”, then “Devices & Services”, in the “Helpers” tab. Enter a name, select your humidity sensor, and choose the desired precision (for example 3). The time unit can be seconds or minutes depending on your preference. Other options are not suitable for this use case.

Once the derivative is configured, import it into Node-Red and define a trigger threshold as shown below.

Figure 5 Derivative threshold

This threshold depends on your bathroom, your environment, and especially the sensor placement. Ideally, place the sensor above the shower but not too close. To find a reliable value, record a shower session and observe the derivative in the “History” dashboard. Choose a value above the noise level. If you get too many false detections, increase the threshold or duration, and if the automation does not detect showers well enough, simply decrease them.

When a shower is detected, we check that we are within the correct time range (no maximum brightness at night and no flashing) before continuing the automation.

Figure 6 Detect shower

An “inject” node can also be added to test your automation.

Counter management

To handle the flashes, we will use a trigger node and a counter that increments every 5 minutes. Each counter value triggers a flash with a different color.

Below, to make things easier to understand, you will find the full section related to activation and counter management, since all elements are connected. Feel free to zoom into different parts if needed.

Figure 7 Manage activations

You must make sure to properly reset the trigger and the counter, otherwise the counter may get stuck. For example, when the counter reaches 4, it must be reset to start again from 1. The same applies when the light is turned off.

For the trigger, simply send a boolean set to true and resend it every 5 minutes as long as the light is on and a shower has been detected.

Figure 8 Trigger options

The trigger must also be reset when the counter reaches its limit or if the light is turned off.

For the counter, select the “increment” mode and enable both outputs.

Figure 9 Counter options

If you want more colors, simply increase the upper limit of the counter.

For the counter reset options, you need to send a boolean set to “true” when triggered:

Figure 10 Reset options

The counter reset is triggered when the light is turned off or when the counter limit is reached, so that when the light is turned back on, the automation starts again from its initial state.

Once this part is correctly set up, we can move on to the flash management.

Flash management

If you made it this far, you have already completed the hardest part. Here, we will manage the light flashes sent every 5 minutes to notify the user.

The principle is simple: each counter value corresponds to a flash of a specific color. In this tutorial, we use primary colors (red, green, blue), but you can choose any colors you like.

Below is the full flash management:

Figure 11 Manage the flashs

In each branch, we first check that the light is still on, then we change the color:

Figure 12 Green flash

In the action node, add the corresponding configuration in “Data”, for example for green: [0, 255, 0, 0]. Then duplicate this branch for blue [0, 0, 255, 0] and red [255, 0, 0, 0]. The last branch keeps the red color before sending the notification.

How to send a notification ?

When the counter reaches its upper limit, we keep the light red, and if it is still on, it likely means someone forgot to turn it off. In this case, we will send a notification with actions.

Figure 13 Send notification

We use a “delay” node set to 5 minutes, then a trigger node that repeats the notification every 15 minutes.

For the delay node, simply select the options as shown below:

Figure 14 Delay for notification

For the trigger node, it is configured the same way as above except it repeats every 15 minutes:

Figure 15 Trigger for notification

Before sending the notification, we check whether the light has been turned off in the meantime. If it has, we send a reset to the trigger to cancel future notifications.

If the light is still on, we define the notification message using a change node in msg.message, then send the notification using an action node.

Figure 16 Message for notification

In the action node that sends the notification, we will have:

Figure 17 Actions for notification

In the configuration, make sure to select the notification action. For actions, we will see in the next section how to create a notification with predefined actions.

How to create a notification with actions?

In the notification we generate, we will include actions such as “Turn off the light”, “Ignore”, and “Remind later”. To do this, add the following code in the “Data” section of the action node:

Figure 18 Actions to do

The “title” field is the notification title. The message will contain msg.message. The “actions” parameter groups all available actions. The “action” field will be used as an identifier later.

Once this block is configured, we can move on to handling the actions.

Figure 19 Manage actions

To handle actions, we retrieve them in the “event” node, which is configured as shown below:

Figure 20 Events for actions

The only field to fill in is the event type. To find it, go to “Developer Tools”, then “Events”:

Figure 21 List of events

On the right, you will see the list of all events, and you just need to select the correct one for this tutorial.

To process each notification action, we use a switch node configured as shown below:

Figure 22 Switch node

For the property, select “event.action”, which corresponds to the received actions. Then, for each case, enter the correct name of the actions you previously defined.

So, when the action is “turn off the light”, we trigger the node to turn off the light and also reset the trigger to stop further notifications. For the “remind later” action, we do nothing so that the notification continues every 15 minutes. Finally, for the “ignore” action, we simply reset the trigger to stop notifications.

Conclusion

With this automation, you have a cool and practical way to track your shower duration and get notified if you forget to turn off the light, with the ability to turn it off directly from the notification.

If you do not want to build the automation yourself, you can download the file to import into Node-Red. Make sure to adjust the configuration to match your setup.

Downloads

You can import the Node-Red flow:

Node-RED Flow
[
  {
    "id": "90f3f488494fd855",
    "type": "tab",
    "label": "Smart Bathroom timer light",
    "disabled": false,
    "info": "",
    "env": []
  },
  {
    "id": "dd75a0f57d7d6f9d",
    "type": "server-state-changed",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 6,
    "outputs": 2,
    "exposeAsEntityConfig": "",
    "entities": {
      "entity": [
        "sensor.temperature_salle_de_bain_humidity_deriv_tuto"
      ],
      "substring": [],
      "regex": []
    },
    "outputInitially": false,
    "stateType": "str",
    "ifState": "5",
    "ifStateType": "num",
    "ifStateOperator": "gte",
    "outputOnlyOnStateChange": true,
    "for": "30",
    "forType": "num",
    "forUnits": "seconds",
    "ignorePrevStateNull": false,
    "ignorePrevStateUnknown": false,
    "ignorePrevStateUnavailable": false,
    "ignoreCurrentStateUnknown": false,
    "ignoreCurrentStateUnavailable": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "eventData"
      },
      {
        "property": "topic",
        "propertyType": "msg",
        "value": "",
        "valueType": "triggerId"
      }
    ],
    "x": 250,
    "y": 140,
    "wires": [
      [
        "170b734d38690ba6"
      ],
      []
    ]
  },
  {
    "id": "170b734d38690ba6",
    "type": "time-range-switch",
    "z": "90f3f488494fd855",
    "name": "",
    "lat": "",
    "lon": "",
    "startTime": "06:00",
    "endTime": "23:59",
    "startOffset": 0,
    "endOffset": 0,
    "x": 650,
    "y": 140,
    "wires": [
      [
        "da44604199018dde"
      ],
      []
    ]
  },
  {
    "id": "da44604199018dde",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 980,
    "y": 120,
    "wires": [
      [
        "945d5a5c791f23c6"
      ],
      []
    ]
  },
  {
    "id": "3943c6b06e13406f",
    "type": "inject",
    "z": "90f3f488494fd855",
    "name": "",
    "props": [
      {
        "p": "payload"
      },
      {
        "p": "topic",
        "vt": "str"
      }
    ],
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "x": 370,
    "y": 80,
    "wires": [
      [
        "170b734d38690ba6"
      ]
    ]
  },
  {
    "id": "945d5a5c791f23c6",
    "type": "trigger",
    "z": "90f3f488494fd855",
    "name": "",
    "op1": "true",
    "op2": "0",
    "op1type": "bool",
    "op2type": "str",
    "duration": "-5",
    "extend": false,
    "overrideDelay": false,
    "units": "min",
    "reset": "",
    "bytopic": "all",
    "topic": "topic",
    "outputs": 1,
    "x": 1530,
    "y": 260,
    "wires": [
      [
        "d411b334c6ae3652"
      ]
    ]
  },
  {
    "id": "d411b334c6ae3652",
    "type": "counter",
    "z": "90f3f488494fd855",
    "name": "",
    "init": "0",
    "step": "1",
    "lower": "0",
    "upper": "4",
    "mode": "increment",
    "outputs": 2,
    "x": 1820,
    "y": 260,
    "wires": [
      [
        "fb18880933478fdb"
      ],
      []
    ]
  },
  {
    "id": "fb18880933478fdb",
    "type": "switch",
    "z": "90f3f488494fd855",
    "name": "",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
      {
        "t": "eq",
        "v": "1",
        "vt": "num"
      },
      {
        "t": "eq",
        "v": "2",
        "vt": "num"
      },
      {
        "t": "eq",
        "v": "3",
        "vt": "num"
      },
      {
        "t": "eq",
        "v": "4",
        "vt": "num"
      }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 4,
    "x": 2010,
    "y": 260,
    "wires": [
      [
        "2b9fb2b30d572760"
      ],
      [
        "aa8b420d8887486d"
      ],
      [
        "672683edbf0b497e"
      ],
      [
        "07279c0739e9de0a",
        "e9822664516e8456"
      ]
    ]
  },
  {
    "id": "2b9fb2b30d572760",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 2300,
    "y": 120,
    "wires": [
      [
        "715a5e7ce7d94fad"
      ],
      [
        "8cb9cc668e195387"
      ]
    ]
  },
  {
    "id": "715a5e7ce7d94fad",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\": 254,\t    \"rgbw_color\": [\t        0,\t        255,\t        0,\t        0\t    ]\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 2610,
    "y": 100,
    "wires": [
      [
        "9ce9b315187bd534"
      ]
    ]
  },
  {
    "id": "9ce9b315187bd534",
    "type": "ha-wait-until",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "entities": {
      "entity": [
        "light.plafonnier_sdb"
      ],
      "substring": [],
      "regex": []
    },
    "property": "payload",
    "comparator": "is",
    "value": "false",
    "valueType": "bool",
    "timeout": "2",
    "timeoutType": "num",
    "timeoutUnits": "seconds",
    "checkCurrentState": true,
    "blockInputOverrides": true,
    "outputProperties": [],
    "x": 2800,
    "y": 100,
    "wires": [
      [],
      [
        "5e236abc2733b453"
      ]
    ]
  },
  {
    "id": "5e236abc2733b453",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\":254,\t    \"color_temp_kelvin\":5000\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 3010,
    "y": 100,
    "wires": [
      []
    ]
  },
  {
    "id": "aa8b420d8887486d",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 2300,
    "y": 180,
    "wires": [
      [
        "79ad25a8fb572e7f"
      ],
      [
        "07a5d2086e061589"
      ]
    ]
  },
  {
    "id": "79ad25a8fb572e7f",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\": 254,\t    \"rgbw_color\": [\t        0,\t        0,\t        255,\t        0\t    ]\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 2610,
    "y": 160,
    "wires": [
      [
        "d5d3bad2ab668bbf"
      ]
    ]
  },
  {
    "id": "d5d3bad2ab668bbf",
    "type": "ha-wait-until",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "entities": {
      "entity": [
        "light.plafonnier_sdb"
      ],
      "substring": [],
      "regex": []
    },
    "property": "payload",
    "comparator": "is",
    "value": "false",
    "valueType": "bool",
    "timeout": "2",
    "timeoutType": "num",
    "timeoutUnits": "seconds",
    "checkCurrentState": true,
    "blockInputOverrides": true,
    "outputProperties": [],
    "x": 2800,
    "y": 160,
    "wires": [
      [],
      [
        "7108f57c661bd060"
      ]
    ]
  },
  {
    "id": "7108f57c661bd060",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\":254,\t    \"color_temp_kelvin\":5000\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 3010,
    "y": 160,
    "wires": [
      []
    ]
  },
  {
    "id": "672683edbf0b497e",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 2300,
    "y": 240,
    "wires": [
      [
        "394447a6e227f7fb"
      ],
      [
        "6c10c1a97004e521"
      ]
    ]
  },
  {
    "id": "394447a6e227f7fb",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\": 254,\t    \"rgbw_color\": [\t        255,\t        0,\t        0,\t        0\t    ]\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 2610,
    "y": 220,
    "wires": [
      [
        "ebd1eab1c2be4aac"
      ]
    ]
  },
  {
    "id": "ebd1eab1c2be4aac",
    "type": "ha-wait-until",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "entities": {
      "entity": [
        "light.plafonnier_sdb"
      ],
      "substring": [],
      "regex": []
    },
    "property": "payload",
    "comparator": "is",
    "value": "false",
    "valueType": "bool",
    "timeout": "2",
    "timeoutType": "num",
    "timeoutUnits": "seconds",
    "checkCurrentState": true,
    "blockInputOverrides": true,
    "outputProperties": [],
    "x": 2800,
    "y": 220,
    "wires": [
      [],
      [
        "62d9725a1de02cc8"
      ]
    ]
  },
  {
    "id": "62d9725a1de02cc8",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\":254,\t    \"color_temp_kelvin\":5000\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 3010,
    "y": 220,
    "wires": [
      []
    ]
  },
  {
    "id": "07279c0739e9de0a",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 2300,
    "y": 300,
    "wires": [
      [
        "f7ea51b0d902d034"
      ],
      [
        "1931eb8fe19fd6c6"
      ]
    ]
  },
  {
    "id": "f7ea51b0d902d034",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\": 254,\t    \"rgbw_color\": [\t        255,\t        0,\t        0,\t        0\t    ]\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 2610,
    "y": 280,
    "wires": [
      [
        "63a8daf5990a2b3e"
      ]
    ]
  },
  {
    "id": "e9822664516e8456",
    "type": "change",
    "z": "90f3f488494fd855",
    "name": "",
    "rules": [
      {
        "t": "set",
        "p": "reset",
        "pt": "msg",
        "to": "true",
        "tot": "bool"
      }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1820,
    "y": 400,
    "wires": [
      [
        "d411b334c6ae3652",
        "945d5a5c791f23c6"
      ]
    ]
  },
  {
    "id": "63a8daf5990a2b3e",
    "type": "delay",
    "z": "90f3f488494fd855",
    "name": "",
    "pauseType": "delay",
    "timeout": "5",
    "timeoutUnits": "minutes",
    "rate": "1",
    "nbRateUnits": "1",
    "rateUnits": "second",
    "randomFirst": "1",
    "randomLast": "5",
    "randomUnits": "seconds",
    "drop": false,
    "allowrate": false,
    "outputs": 1,
    "x": 2900,
    "y": 280,
    "wires": [
      [
        "979c24c70d0413ef"
      ]
    ]
  },
  {
    "id": "979c24c70d0413ef",
    "type": "trigger",
    "z": "90f3f488494fd855",
    "name": "",
    "op1": "true",
    "op2": "0",
    "op1type": "bool",
    "op2type": "str",
    "duration": "-15",
    "extend": false,
    "overrideDelay": false,
    "units": "min",
    "reset": "",
    "bytopic": "all",
    "topic": "topic",
    "outputs": 1,
    "x": 3170,
    "y": 280,
    "wires": [
      [
        "75313587bf266329"
      ]
    ]
  },
  {
    "id": "75313587bf266329",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 3460,
    "y": 280,
    "wires": [
      [
        "26b878f6e1643b86"
      ],
      [
        "f63a21e6f3e8870a"
      ]
    ]
  },
  {
    "id": "26b878f6e1643b86",
    "type": "change",
    "z": "90f3f488494fd855",
    "name": "",
    "rules": [
      {
        "t": "set",
        "p": "message",
        "pt": "msg",
        "to": "The bathroom light is on",
        "tot": "str"
      }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 3750,
    "y": 260,
    "wires": [
      [
        "af527b49afc483a1"
      ]
    ]
  },
  {
    "id": "af527b49afc483a1",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "notify.mobile_app_ipad_abdoulaye",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [],
    "labelId": [],
    "data": "{\t    \"title\":\"Light On\",\t    \"message\":msg.message,\t    \"data\":{\t        \"actions\":[\t            {\t                \"action\":\"Turn_off\",\t                \"title\":\"Turn Off\",\t                \"icon\":\"sfsymbols:poweroff\"\t            },\t            {\t               \"action\":\"Remind\",\t                \"title\":\"Remind Later\",\t                \"icon\":\"sfsymbols:clock\" \t            },\t            {\t               \"action\":\"Ignore\",\t                \"title\":\"Ignore: Stop reminds\",\t                \"icon\":\"sfsymbols:xmark\",\t                \"destructive\":true\t            }\t            \t        ]\t    }\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "notify",
    "service": "mobile_app_ipad_abdoulaye",
    "x": 4060,
    "y": 260,
    "wires": [
      []
    ]
  },
  {
    "id": "0eabad8008a4794e",
    "type": "server-events",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "exposeAsEntityConfig": "",
    "eventType": "mobile_app_notification_action",
    "eventData": "",
    "waitForRunning": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "",
        "valueType": "eventData"
      },
      {
        "property": "topic",
        "propertyType": "msg",
        "value": "$outputData(\"eventData\").event_type",
        "valueType": "jsonata"
      }
    ],
    "x": 2530,
    "y": 480,
    "wires": [
      [
        "34ecaa892271090e"
      ]
    ]
  },
  {
    "id": "34ecaa892271090e",
    "type": "switch",
    "z": "90f3f488494fd855",
    "name": "",
    "property": "payload.event.action",
    "propertyType": "msg",
    "rules": [
      {
        "t": "eq",
        "v": "Turn_off",
        "vt": "str"
      },
      {
        "t": "eq",
        "v": "Remind",
        "vt": "str"
      },
      {
        "t": "eq",
        "v": "Ignore",
        "vt": "str"
      }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 3,
    "x": 2810,
    "y": 480,
    "wires": [
      [
        "b03f0c25157937f9"
      ],
      [],
      [
        "f63a21e6f3e8870a"
      ]
    ]
  },
  {
    "id": "b03f0c25157937f9",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_off",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_off",
    "x": 2970,
    "y": 420,
    "wires": [
      [
        "f63a21e6f3e8870a"
      ]
    ]
  },
  {
    "id": "f63a21e6f3e8870a",
    "type": "change",
    "z": "90f3f488494fd855",
    "name": "",
    "rules": [
      {
        "t": "set",
        "p": "reset",
        "pt": "msg",
        "to": "true",
        "tot": "bool"
      }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 3200,
    "y": 460,
    "wires": [
      [
        "979c24c70d0413ef",
        "cf4910afc512f178"
      ]
    ]
  },
  {
    "id": "e9b370ed83b8e3ef",
    "type": "link in",
    "z": "90f3f488494fd855",
    "name": "Light off",
    "links": [
      "07a5d2086e061589",
      "1931eb8fe19fd6c6",
      "6c10c1a97004e521",
      "8cb9cc668e195387"
    ],
    "x": 1645,
    "y": 420,
    "wires": [
      [
        "e9822664516e8456"
      ]
    ]
  },
  {
    "id": "8cb9cc668e195387",
    "type": "link out",
    "z": "90f3f488494fd855",
    "name": "Light off",
    "mode": "link",
    "links": [
      "e9b370ed83b8e3ef"
    ],
    "x": 2505,
    "y": 140,
    "wires": []
  },
  {
    "id": "07a5d2086e061589",
    "type": "link out",
    "z": "90f3f488494fd855",
    "name": "Light off",
    "mode": "link",
    "links": [
      "e9b370ed83b8e3ef"
    ],
    "x": 2485,
    "y": 200,
    "wires": []
  },
  {
    "id": "6c10c1a97004e521",
    "type": "link out",
    "z": "90f3f488494fd855",
    "name": "Light off",
    "mode": "link",
    "links": [
      "e9b370ed83b8e3ef"
    ],
    "x": 2495,
    "y": 260,
    "wires": []
  },
  {
    "id": "1931eb8fe19fd6c6",
    "type": "link out",
    "z": "90f3f488494fd855",
    "name": "Light off",
    "mode": "link",
    "links": [
      "e9b370ed83b8e3ef"
    ],
    "x": 2505,
    "y": 320,
    "wires": []
  },
  {
    "id": "7fb9bdd64ccae6fa",
    "type": "link in",
    "z": "90f3f488494fd855",
    "name": "link in 6",
    "links": [
      "cf4910afc512f178"
    ],
    "x": 1675,
    "y": 200,
    "wires": [
      [
        "d411b334c6ae3652"
      ]
    ]
  },
  {
    "id": "cf4910afc512f178",
    "type": "link out",
    "z": "90f3f488494fd855",
    "name": "Rst Cnt",
    "mode": "link",
    "links": [
      "7fb9bdd64ccae6fa"
    ],
    "x": 3385,
    "y": 460,
    "wires": []
  },
  {
    "id": "5932ae5eb6782406",
    "type": "mqtt in",
    "z": "90f3f488494fd855",
    "name": "Button",
    "topic": "zigbee2mqtt/Bouton_Sdb/action",
    "qos": "2",
    "datatype": "auto-detect",
    "broker": "5914a38474afa853",
    "nl": false,
    "rap": true,
    "rh": 0,
    "inputs": 0,
    "x": 90,
    "y": 440,
    "wires": [
      [
        "94e233e282e93c6d"
      ]
    ]
  },
  {
    "id": "94e233e282e93c6d",
    "type": "switch",
    "z": "90f3f488494fd855",
    "name": "",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
      {
        "t": "eq",
        "v": "on",
        "vt": "str"
      },
      {
        "t": "eq",
        "v": "off",
        "vt": "str"
      }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 2,
    "x": 350,
    "y": 440,
    "wires": [
      [
        "bdcc71e469d2654c"
      ],
      [
        "093f22c733d73318"
      ]
    ]
  },
  {
    "id": "093f22c733d73318",
    "type": "change",
    "z": "90f3f488494fd855",
    "name": "",
    "rules": [
      {
        "t": "set",
        "p": "reset",
        "pt": "msg",
        "to": "true",
        "tot": "bool"
      }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 620,
    "y": 480,
    "wires": [
      [
        "945d5a5c791f23c6",
        "d411b334c6ae3652"
      ]
    ]
  },
  {
    "id": "bdcc71e469d2654c",
    "type": "api-current-state",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 3,
    "outputs": 2,
    "halt_if": "off",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "light.plafonnier_sdb",
    "state_type": "str",
    "blockInputOverrides": true,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "string",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 600,
    "y": 340,
    "wires": [
      [
        "b7b3d933acfeeb9a"
      ],
      [
        "53a8860ae310af7e"
      ]
    ]
  },
  {
    "id": "53a8860ae310af7e",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_off",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_off",
    "x": 870,
    "y": 380,
    "wires": [
      []
    ]
  },
  {
    "id": "b7b3d933acfeeb9a",
    "type": "time-range-switch",
    "z": "90f3f488494fd855",
    "name": "",
    "lat": "",
    "lon": "",
    "startTime": "06:00",
    "endTime": "23:59",
    "startOffset": 0,
    "endOffset": 0,
    "x": 870,
    "y": 260,
    "wires": [
      [
        "f23fc98dd63a9b15"
      ],
      [
        "8d4b6719171e86ee"
      ]
    ]
  },
  {
    "id": "f23fc98dd63a9b15",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\":254,\t    \"color_temp_kelvin\":5000\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 1050,
    "y": 220,
    "wires": [
      []
    ]
  },
  {
    "id": "8d4b6719171e86ee",
    "type": "api-call-service",
    "z": "90f3f488494fd855",
    "name": "",
    "server": "4e2c03c1.d491cc",
    "version": 7,
    "debugenabled": false,
    "action": "light.turn_on",
    "floorId": [],
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "light.plafonnier_sdb"
    ],
    "labelId": [],
    "data": "{\t    \"brightness\":90,\t    \"color_temp_kelvin\":2200\t}",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [],
    "queue": "none",
    "blockInputOverrides": true,
    "domain": "light",
    "service": "turn_on",
    "x": 1050,
    "y": 300,
    "wires": [
      []
    ]
  },
  {
    "id": "c7e223e9ac7edca7",
    "type": "comment",
    "z": "90f3f488494fd855",
    "name": "Node-Red automation create a smart bathroom lighting system with Home assistant and Node-Red : www.smarthome3d.com",
    "info": "",
    "x": 420,
    "y": 20,
    "wires": []
  },
  {
    "id": "4e2c03c1.d491cc",
    "type": "server",
    "name": "Home Assistant",
    "addon": true,
    "rejectUnauthorizedCerts": true,
    "ha_boolean": "",
    "connectionDelay": false,
    "cacheJson": false,
    "heartbeat": false,
    "heartbeatInterval": "",
    "statusSeparator": "",
    "enableGlobalContextStore": false
  },
  {
    "id": "5914a38474afa853",
    "type": "mqtt-broker",
    "name": "Mqtt local",
    "broker": "core-mosquitto.local.hass.io",
    "port": "1883",
    "clientid": "",
    "autoConnect": true,
    "usetls": false,
    "protocolVersion": "4",
    "keepalive": "60",
    "cleansession": true,
    "autoUnsubscribe": true,
    "birthTopic": "",
    "birthQos": "0",
    "birthRetain": "false",
    "birthPayload": "",
    "birthMsg": {},
    "closeTopic": "",
    "closeQos": "0",
    "closeRetain": "false",
    "closePayload": "",
    "closeMsg": {},
    "willTopic": "",
    "willQos": "0",
    "willRetain": "false",
    "willPayload": "",
    "willMsg": {},
    "userProps": "",
    "sessionExpiry": ""
  },
  {
    "id": "8101616283c75939",
    "type": "global-config",
    "env": [],
    "modules": {
      "node-red-contrib-home-assistant-websocket": "0.80.3",
      "node-red-contrib-time-range-switch": "1.2.0",
      "node-red-contrib-counter": "0.1.6"
    }
  }
]

Recommended articles

Home Assistant 2026-4

In this new update, several particularly interesting features have been introduced. I’ve had it installed for a while now and, as far as I know, no major regressions have been reported. You...

iOS Shortcuts 26-4

The iOS 26.4 update brings several very interesting new features for iOS Shortcuts users. In this short post, I present the new actions available in iOS 26.4 Shortcuts, along with a few...

How to Synchronize Multiple Alarms with Home Assistant

Are you tired of missing your alarms or having to configure everything manually in Home Assistant all the time? In this tutorial, discover how to automatically synchronize multiple iPhone...

Comments

No comments yet.