Can't sleep! Try this

That worked for me. Thanks!

Great - hope that it proves interesting to you. Amazingly it needs to be fairly bright so you can see the on/off sequence with your eyes closed. Blue is a good choice of colour. The sequence between off-to-on and on-to-off in this setup is equal. The on-to-off step is supposed to be longer. The sequence is suppose to run for about 15 minutes what I have works for me.

Did a Yaml version of this happen? I’m interested if so. Don’t have NR so not keen to pursue that route.

@Isablend - no a yaml version does not exist (yet). I renamed the flow.json file to flow.yaml so that I could upload it. To import this you will need node-red.

I couldn’t resist having a go, but ultimately failed in writing this in yaml, just couldn’t get the timing right, so i gave it a go using appdaemon, and it turns out to be a relatively easy thing to do. Having spent a bit of time learning about appdaemon, I think I will use it for more complex automations in future.

So I have a light defined and in input boolean to allow switching on and off (also allows for an Alexa initiation). I’ve defined 5 variables in the accompanying .yaml file which define the number of minutes for the thing to run, the starting breaths per minute and the ending breaths per minute, along with the maximum and minimum light settings (expressed as a percentage).

The appdaemon code is then as follows;

import appdaemon.plugins.hass.hassapi as hass
import time

# App to turn a light into a sleep inducer 
# Turns the light on and off to mirror breathing pattern
# slowly reducing the rate of breaths over a stated period of time

class Sleep_Inducer(hass.Hass):

    # Initialise all of the necessary variables for the app 
    def initialize(self):
        self.si_min = int(self.args["sleep_inducer_minutes"])
        self.st_bpm = int(self.args["starting_breaths_per_minute"])
        self.end_bpm = int(self.args["ending_breaths_per_minute"])
        self.max_bri = int((255/100)*int( self.args["max_brightness"]))
        self.min_bri = int((255/100)*int( self.args["min_brightness"]))

        self.listen_state(self.SleepInducerOn, "input_boolean.sleep_inducer", new="on")
 
    def SleepInducerOn(self, entity, attribute, old, new, kwargs):
        if new == 'on' :

           # execute for a set number of minutes 
           for minute_count in range(self.si_min):

               # calculate the breath time for this minute's iteration
               breath_number = int( ( ( -0.125 * ( self.st_bpm - self.end_bpm ) ) * minute_count ) + self.st_bpm )
               breath_time = float( 60 / ( ( ( -0.125 * ( self.st_bpm - self.end_bpm ) ) * minute_count ) + self.st_bpm ) )

               # set number of times in the current minute to breath
               for breath_count in range(int(breath_number)):

                   # breath in - 3/5 of breath_time
                   breath_in=breath_time*(3/5)
                   self.turn_on("light.sleep_inducer",
                                color_name = "blue",
                                transition = int(breath_in), 
                                brightness = self.max_bri)
                   # pause to let the light catch-up
                   time.sleep(breath_in)

                   breath_out=breath_time*(2/5) 
                   # breath out - 2/5 of breath_time
                   self.turn_on("light.sleep_inducer",
                                transition = int(breath_out), 
                                brightness = self.min_bri)
                   # pause to let the light catch-up
                   time.sleep(breath_out)

                   # check that it has not been cancelled
                   continue_si=self.get_state('input_boolean.sleep_inducer')
                   
                   # drop out of breath_count loop
                   if continue_si=='off' :
                      break

               # drop out of minute_count loop
               if continue_si=='off' :
                  break

           # turn off the sleep_inducer switch
           self.turn_off("input_boolean.sleep_inducer")
           # turn the light off
           self.turn_off("light.sleep_inducer")

I’m sure it’s not perfect, but it works and has opened up a whole new area for me to investigate.

2 Likes