Can't sleep! Try this


#1

I saw a Dodow on Amazon and then on YouTube. https://www.youtube.com/watch?v=Z6Q7yhrv2bs

The idea is to synchronise your breathing with the light. It start with 11 breaths a minute and after 8 minutes slows to 5 breaths a minute.

I thought, I can do that with a Hue light, so I tried in NodeRed and the results, early days yet, is good.

Here is the NodeRed script. The nodes that turn the lights on and off will need to be modified for your setup.

[
{
“id”: “874b3bab.0c2928”,
“type”: “tab”,
“label”: “Hue for bed”,
“disabled”: false,
“info”: “”
},
{
“id”: “c63feb00.6cd608”,
“type”: “inject”,
“z”: “874b3bab.0c2928”,
“name”: “off”,
“topic”: “”,
“payload”: “off”,
“payloadType”: “str”,
“repeat”: “”,
“crontab”: “”,
“once”: false,
“onceDelay”: 0.1,
“x”: 130,
“y”: 160,
“wires”: [
[
“d1642459.6bb5f8”
]
]
},
{
“id”: “af8e22e0.d49e7”,
“type”: “api-call-service”,
“z”: “874b3bab.0c2928”,
“name”: “Light on”,
“server”: “f7a0cb3b.2a4c98”,
“service_domain”: “homeassistant”,
“service”: “turn_on”,
“data”: “{“entity_id”:“light.bedroom”,“transition”:3,“rgb_color”:[10,10,255],“brightness”:190}”,
“render_data”: false,
“mergecontext”: “”,
“output_location”: “payload”,
“output_location_type”: “msg”,
“x”: 804,
“y”: 95,
“wires”: [
[]
]
},
{
“id”: “8ba022f3.cdeb6”,
“type”: “function”,
“z”: “874b3bab.0c2928”,
“name”: “Build delay”,
“func”: “const deltaDelay = 75.757576\nconst initDelay = 2730\nconst loops = 80\nconst delayList = []\n\nconst waitFor = delay => new Promise(resolve => timer = setTimeout(resolve, delay));\nlet timer = {}\n\nlet time = initDelay\nlet onOff = false\n\n// We are starting so we have not been cancelled\nflow.set(‘cancelTimeout’,false);\n\nasync function sendMsgAfterDelay() {\n for (const item of delayList) {\n node.send( { “onOff”: item.onOff ? “on” : “off”, “transition”: Math.trunc(item.time / 1000) });\n await waitFor(item.time);\n flow.set(‘timer’, timer)\n if(flow.get(‘cancelTimeout’)) {\n break;\n }\n }\n if(flow.get(‘cancelTimeout’) === false) {\n node.send( { “onOff”: “lightoff”, “transition”: 0 })\n await waitFor(5000);\n node.send( { “onOff”: “playmusic”, “transition”: 0 })\n }\n}\n\nfor (let loop = 0; loop < loops; loop++) {\n time += deltaDelay\n onOff = !onOff\n delayList.push({ time: time, onOff: onOff })\n}\nsendMsgAfterDelay()\n”,
“outputs”: 1,
“noerr”: 0,
“x”: 450,
“y”: 160,
“wires”: [
[
“6810a2b5.6d6e9c”
]
]
},
{
“id”: “7d7ea2e.38b8a5c”,
“type”: “api-call-service”,
“z”: “874b3bab.0c2928”,
“name”: “Light off”,
“server”: “f7a0cb3b.2a4c98”,
“service_domain”: “homeassistant”,
“service”: “turn_on”,
“data”: “{“entity_id”:“light.bedroom”,“transition”:3,“rgb_color”:[10,10,255],“brightness”:20}”,
“render_data”: false,
“mergecontext”: “”,
“output_location”: “payload”,
“output_location_type”: “msg”,
“x”: 804,
“y”: 155,
“wires”: [
[]
]
},
{
“id”: “6810a2b5.6d6e9c”,
“type”: “switch”,
“z”: “874b3bab.0c2928”,
“name”: “On or Off”,
“property”: “onOff”,
“propertyType”: “msg”,
“rules”: [
{
“t”: “eq”,
“v”: “on”,
“vt”: “str”
},
{
“t”: “eq”,
“v”: “off”,
“vt”: “str”
},
{
“t”: “eq”,
“v”: “lightoff”,
“vt”: “str”
},
{
“t”: “eq”,
“v”: “playmusic”,
“vt”: “str”
}
],
“checkall”: “true”,
“repair”: false,
“outputs”: 4,
“x”: 600,
“y”: 160,
“wires”: [
[
“af8e22e0.d49e7”
],
[
“7d7ea2e.38b8a5c”
],
[
“8d73ddaf.ecc15”
],
[
“4ab38d3d.b28bb4”
]
]
},
{
“id”: “266a8537.6865da”,
“type”: “alexa-local”,
“z”: “874b3bab.0c2928”,
“devicename”: “bed time”,
“inputtrigger”: false,
“x”: 140,
“y”: 240,
“wires”: [
[
“d1642459.6bb5f8”
]
]
},
{
“id”: “2e842800.cd0db8”,
“type”: “debug”,
“z”: “874b3bab.0c2928”,
“name”: “”,
“active”: true,
“tosidebar”: true,
“console”: false,
“tostatus”: false,
“complete”: “true”,
“x”: 790,
“y”: 40,
“wires”: []
},
{
“id”: “8d73ddaf.ecc15”,
“type”: “api-call-service”,
“z”: “874b3bab.0c2928”,
“name”: “Light off completely”,
“server”: “f7a0cb3b.2a4c98”,
“service_domain”: “homeassistant”,
“service”: “turn_off”,
“data”: “{“entity_id”:“light.bedroom”,“transition”:3}”,
“render_data”: false,
“mergecontext”: “”,
“output_location”: “payload”,
“output_location_type”: “msg”,
“x”: 834,
“y”: 220,
“wires”: [
[]
]
},
{
“id”: “4ab38d3d.b28bb4”,
“type”: “api-call-service”,
“z”: “874b3bab.0c2928”,
“name”: “Play music”,
“server”: “f7a0cb3b.2a4c98”,
“service_domain”: “script”,
“service”: “play_ocean”,
“data”: “”,
“render_data”: false,
“mergecontext”: “”,
“output_location”: “payload”,
“output_location_type”: “msg”,
“x”: 814,
“y”: 280,
“wires”: [
[]
]
},
{
“id”: “d1642459.6bb5f8”,
“type”: “switch”,
“z”: “874b3bab.0c2928”,
“name”: “on/off”,
“property”: “payload”,
“propertyType”: “msg”,
“rules”: [
{
“t”: “eq”,
“v”: “on”,
“vt”: “str”
},
{
“t”: “eq”,
“v”: “off”,
“vt”: “str”
}
],
“checkall”: “true”,
“repair”: false,
“outputs”: 2,
“x”: 290,
“y”: 212,
“wires”: [
[
“8ba022f3.cdeb6”
],
[
“c9b38e95.7091a”
]
]
},
{
“id”: “339dc57.e17bf3a”,
“type”: “inject”,
“z”: “874b3bab.0c2928”,
“name”: “on”,
“topic”: “”,
“payload”: “on”,
“payloadType”: “str”,
“repeat”: “”,
“crontab”: “”,
“once”: false,
“onceDelay”: 0.1,
“x”: 130,
“y”: 100,
“wires”: [
[
“d1642459.6bb5f8”
]
]
},
{
“id”: “c9b38e95.7091a”,
“type”: “function”,
“z”: “874b3bab.0c2928”,
“name”: “Cancel function”,
“func”: “// We have been called so we need to cancel\nflow.set(‘cancelTimeout’,true);\nclearTimeout(flow.get(‘timer’))\n”,
“outputs”: 1,
“noerr”: 0,
“x”: 580,
“y”: 220,
“wires”: [
[
“8d73ddaf.ecc15”
]
]
},
{
“id”: “f7a0cb3b.2a4c98”,
“type”: “server”,
“z”: “”,
“name”: “Home Assistant”
}
]


#2

Save me clicking the link…

Light on = breath in and hold until light off? Or breath in and out before light goes off?

If latter, what to do whilst light off?

Does it slowly reduce the time as 8 minutes pass, or does it suddenly drop to 5 breaths a minute?

Is there an ‘introductory period’ before you start?

How long is the routine in its entirity?

Is there a soundtrack?

Will knock out a yaml version when I understand what it’s about and give it a go :slight_smile:


#3

Light on/off should read light brighter/dimmer. Set these as you see fit and what works for you. I started with on and off and on is too bright and off too dark. As I don’t have a device I was cribbing information from the video.

I use it breathing in during getting brighter and breathing out during getting dimmer.

The frequency gradually changes during the duration. The numbers I used are a good starting point but I think these should be refined. At the moment what I have is linear and perhaps logarithmic may be better.

They is no introduction period - but that is a good idea. No sound track, but the end of mine I do play some white noise. Again, this is up to you. Maybe some meditation music would be good to set the mood. Need to initial focus on the light. We have tried some ambient background music but found we focused on the music and not the light. Now if you could sync the two you may have a winner.

I couldn’t figure out how to do loops in yaml with a varying delay which is why I moved to node. The bulk of the work is done here:
const deltaDelay = 75.757576
const initDelay = 2730
const loops = 80
const delayList = []

const waitFor = delay => new Promise(resolve => timer = setTimeout(resolve, delay));
let timer = {}

let time = initDelay
let onOff = false

// We are starting so we have not been cancelled
flow.set('cancelTimeout',false);

async function sendMsgAfterDelay() {
    for (const item of delayList) {
        node.send( { "onOff": item.onOff ? "on" : "off", "transition": Math.trunc(item.time / 1000) });
        await waitFor(item.time);
        flow.set('timer', timer)
        if(flow.get('cancelTimeout')) {
            break;
        }
    }
    if(flow.get('cancelTimeout') === false) {
        node.send( { "onOff": "lightoff", "transition": 0 })
        await waitFor(5000);
        node.send( { "onOff": "playmusic", "transition": 0 })
    }
}

for (let loop = 0; loop < loops; loop++) {
    time += deltaDelay
    onOff = !onOff
    delayList.push({ time: time, onOff: onOff })
}
sendMsgAfterDelay()

Enjoy.


#4

Cheers, I’ll have a play with it when I get a sec :+1:


#5

Hey I tried to use it with my yeelight bedside lamp but somehow when I try to click the turn button nothing happens but when I link direct the on button to light on the light will turn blue. how can I resolve this. Thanks!


#6

@pronsta I am guessing the problem is I am using Hue lights and you are using Yee light. I don’t know how yeelights work or if these support transitions from one colour/brightness to another.

I suggest you take a look at the parameters for transition with Hue light and contrast these with Yee light

As I don’t have any Yee lights it would be very difficult for me to modify any code and test. Essential what is required is transitioning the light from on colour/brightness to another over the transition period.

Good luck.


#7

Oh I see. Can you tell me the interval and duration of each for on/off? or it is random? maybe I can reproduce it somehow.


#8

Wow great project. On Yeelight, maybe it could be done using: https://www.home-assistant.io/components/light.yeelight/#service-lightyeelight_start_flow


#9

Fun idea. Something like this is probably easily implemented in AppDaemon.


#10

Good work @GeoffAtHome

Did you manage to get anything working in yaml?


#11

For some reason the flow json in the original post is giving me a lot of errors when I try to import it. Has anybody else been able to import it successfully?


#12

@garrettbeachy what errors are you seeing?


#13

@cgtobi You could easier implement this in any language but I choose node-red as it has good integration with HA.


#14

@pronsta the on/off interval is not random. It starts at 2730ms on, then add 75ms to off. Each on adds 75ms to the delay. Each off adds an additional 75ms to delay.

This works for me. Feel free to adjust the values to suit your own needs. What the youtube video referenced in the first post to get the full picture.


#15

When I paste it into the clipboard import box I get “SyntaxError: Unexpected token “ in JSON at position 4” as the first error I see, but when I fix that it just brings up another of the same type.


#16

Hi Geoff, this was by no means meant critical. I can’t judge node-red as I haven’t touched it, probably because the python-style approach used by AppDaemon just fits me.


#17

@cgtobi none taken. It would be good to see how this could be done by AppDaemon as it would be good to get an appreciation of how other tools work. The bulk of the work is actually done in JavaScript and it is not too difficult to port from JavaScript to any other language.

I don’t know how to integrate with HA using Python other than writing custom components.

Let me know when you have something up and running - it will be interesting to learn more.


#18

@garrettbeachy could it be related to the fact I use Alexa to trigger this? In my node-red palette I include:
node-red-contrib-alexa-local, node-red-contrib-bigtimer, node-red-contrib-home-assistant-websocket and node-red-contrib-stoptimer. Others are included but I believe I installed this after installing node-red.


#19

It’s looks more like the json got malformed somehow by the formatting in the original post. Maybe you could try a pastebin or something similar to see if that keeps the formatting?


#20

flows.yaml (4.4 KB)
@garrettbeachy I have uploaded the flows.json as flows.yaml. I cannot upload json contents. You should be able to download and rename the file to .json for importing.