Node-Red Flow Samples/Sharing

I updated my button tap subflow, now it traps doubletap and held events - you can define how many "taps" a held event is.. Previously I was using this for a pico in quick mode but now can be used for buttons like smartthings button or others maybe. Also taps exceeding the 4 by default will get sent through the 4th output - you would need to check the "msg.count" property.

Updated code now on this post:

Here was the original post:

3 Likes

Looking for advice from anyone using lux readings to automate lights. I'm trying to decide what approach would be reasonable or most effective using the "Calculate" node (or any other node that does average, max, min over a period of time). Do you use average readings or max or min? Over what period (minute or more)?

Currently, my automations work well unless there is moving cloud cover causing the lights to cycle on/off. Appreciate any guidance you can provide.

No right answer on this one - it depends on personal tastes, and how fast your lux sensor updates.

I like the smooth node (node-red-node-smooth) for smoothing signals, but there are a number of other nodes that can do it.

Here are some examples of response on my outdoor lux reading that updates 1x/minute (weatherflow weather station).

The trick is how fast you want the automation to react. I don't like the lights shifting frequently/fast, so I use a fairly high filter. Mean 3 or Mean 5 works well for that, with values at the 1x/min frequency. If you want it faster, or your lux readings come in faster/slower you would have to adjust that.

As you would guess, the dips are clouds that went by.

Raw vs Low pass filters:

Raw vs Means:

1 Like

Yeah - This one is an Aeotec MS6 using @csteele’s driver. I have it set to report on a 2 Lux change (works for me since it’s indoors). Since I’m logging all changes, I think I can go back and look how quickly it’s reporting but I’m going to have to find a day that matches cloudy conditions!

I think I may start with a “max” value and 1 minute and see how that goes. Thoughts?

You won't like my thought on using the MS6 for lux control. :slight_smile:

In my OPINION, for GOOD lux control you need something that reports more frequently. For indoor lux I would want something that reports in the order of 5-15s continually so that predictable filtering can be done. Easy to do with a Arduino/esp8266 on mains power, not so easy to do on a battery powered device, or a z sensor on mains power (as they still typically only repeat on change, plus a slow fixed time interval).

That said, go back and look at how it reports on a cloud event. For a sensor that reports infrequently, using a time relay with reset instead of averaging or a filter may be more appropriate.

1 Like

I use these

4 Likes

For my simplistic use as a basic lux detector in NR I created subflow with a set of ranges defined as none/low/medlow/med/medhi/hi and simply key off the lux value. This works well as long as I leave a sufficient enough gap between the ranges. A usb powered MS-6 works great for this..

If I were to get more sophisticated like setting dimming levels or other stuff based on lux however then heck yes - more accurate sensor + much better algorithm like the smoothing node (thanks for the heads up on that btw).

1 Like

Yeah - my MS6 is USB powered, so does report fairly frequently. However, it doesn't look like I have multiple readings in less than a minute.

Could you share the ranges that you have defined? I'm currently using <=20 as "on", >=30 as "off". This works "most" of the time.

Restart Homebridge on HE reboot/power cycle

I was having an issue with Homebridge log showing errors if HE was restarted and Homebridge was not

The errors appear to be harmless but I was looking for a way to automatically restart Homebridge process when HE was restarted. It turns out that the Homebridge UI plug-in has an API that can be accessed from Node-RED.

The following flow automatically restarts Homebridge if HE is restarted.

It uses standard nodes (Change, Delay, Function, HTTP Request) and the node-red-contrib-credentials (node-red-contrib-credentials (node) - Node-RED) for username, password and the IP address/port of the Homebridge server.

The flow is triggered by the link-in from the Hub systemStart location event on another flow. The flow execution is delayed for 2 minutes to ensure that HE has finished rebooting. It then logs into Homebridge and calls the restart API (similar to the user selecting the "restart" button in the Homebridge UI)

Below is the flow if anyone wants it.

NOTE: The log errors seem to be only with the MakerAPI Homebridge plug-in

[{"id":"b4ab3d8b.fdbf5","type":"group","z":"934f1005.6e02","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["f4c6b858.26b3e8","166fcda7.a1102a","695cbfba.6f73a","acf9ac7f.7b6e7","122304c7.f7beeb","e7ca8e9a.de2618","4012e6a2.c3064","e603b57e.6c9968","1122835a.5ff315","bd279032.bec948","8576170d.ec4a38","d98d244.6275758"],"x":43.33332824707031,"y":2490.0000381469727,"w":1339.6667022705078,"h":323.99996185302734},{"id":"f4c6b858.26b3e8","type":"link in","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"","links":["d22ba984.19a1e"],"x":97.33332824707031,"y":2583.0000381469727,"wires":[["166fcda7.a1102a"]]},{"id":"166fcda7.a1102a","type":"change","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Delete Payload","rules":[{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":236.33334350585938,"y":2582,"wires":[["695cbfba.6f73a"]]},{"id":"695cbfba.6f73a","type":"delay","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Delay 2 Mins","pauseType":"delay","timeout":"2","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":431.3333435058594,"y":2583,"wires":[["acf9ac7f.7b6e7"]]},{"id":"acf9ac7f.7b6e7","type":"credentials","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"","props":[{"value":"payload.username","type":"msg"},{"value":"payload.password","type":"msg"},{"value":"HB_IP","type":"msg"}],"x":177,"y":2652.33349609375,"wires":[["e7ca8e9a.de2618"]]},{"id":"122304c7.f7beeb","type":"inject","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Manual Restart","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":186,"y":2709.33349609375,"wires":[["acf9ac7f.7b6e7"]]},{"id":"e7ca8e9a.de2618","type":"function","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Set Login URL and Headers","func":"//Set URL for Homebrdige login and header for Content Type\n\nmsg.url = msg.HB_IP+'/api/auth/login'\nmsg.headers = 'Content-Type: application/json'\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":401.333251953125,"y":2653.0002365112305,"wires":[["4012e6a2.c3064"]]},{"id":"4012e6a2.c3064","type":"http request","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Login and get Token","method":"POST","ret":"obj","paytoqs":"body","url":"","tls":"","persist":false,"proxy":"","authType":"","x":654.9999542236328,"y":2652.0002059936523,"wires":[["e603b57e.6c9968"]]},{"id":"e603b57e.6c9968","type":"function","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Set Restart URL and Headers","func":"var token = msg.payload.access_token;\nmsg.headers = {\n     Authorization: \"Bearer \"+token\n}\nmsg.url = msg.HB_IP+'/api/server/restart'\n\n//Delete unneeded messager parts\ndelete msg.HB_IP\ndelete msg.payload.access_token\ndelete msg.payload.token_type\ndelete msg.payload.expires_in\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":912.3333129882812,"y":2651.0002059936523,"wires":[["1122835a.5ff315"]]},{"id":"1122835a.5ff315","type":"http request","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Restart Homebridge","method":"PUT","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1172.0000381469727,"y":2650.6669921875,"wires":[["bd279032.bec948"]]},{"id":"bd279032.bec948","type":"debug","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"RESTART RETURN","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1237.0000305175781,"y":2704.33349609375,"wires":[]},{"id":"8576170d.ec4a38","type":"comment","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Restart Homebridge on HE reboot","info":"","x":213.3333282470703,"y":2531.0000381469727,"wires":[]},{"id":"d98d244.6275758","type":"comment","z":"934f1005.6e02","g":"b4ab3d8b.fdbf5","name":"Change Log","info":"2021-05-23: Created","x":139.3333282470703,"y":2773,"wires":[]}]

Hope this helps someone!

1 Like

Wanted to post this here as well in case anyone is interested - this is a very simple example of a Finite State Machine aggregating a "motion sensor" and a "contact sensor" and putting the results in a switch node for fun and easy processing:

1 Like

Putting this here in in case anyone's been experiencing issues with casting TTS to Chromecast groups. I battled with this for months. Basically, the IP/Port for Cast Groups can change from time to time and are therefore super annoying all the time. This flow browses _googlecast._tcp nodes and uses the output to generate the most up to date IP/port for the chosen cast group before sending the TTS request.

Note: I implemented this on an Ubuntu box. You will need to install the avahi-utils package prior to running. For a Windows node-red installation, I'm sure it can be done, but this certainly won't work out of the box without modifications.

[{"id":"ce1430ad.2794e","type":"cast-to-client","z":"7b31a85e.379d78","name":"Google Home - Non-specific","url":"","contentType":"","message":"","language":"en","ip":"","port":"","volume":"","x":1420,"y":420,"wires":[[]],"icon":"node-red-contrib-cast/google-home1.svg"},{"id":"c15ad04f.c266c","type":"looptimer2","z":"7b31a85e.379d78","duration":"2","units":"Second","maxloops":"100","maxtimeout":"1","maxtimeoutunits":"Hour","name":"","x":260,"y":420,"wires":[["d6fbebd5.7edfa8"],[]]},{"id":"84e21e46.de69a","type":"change","z":"7b31a85e.379d78","name":"Prepare Message","rules":[{"t":"move","p":"strArray[7]","pt":"msg","to":"ip","tot":"msg"},{"t":"move","p":"strArray[7]","pt":"msg","to":"port","tot":"msg"},{"t":"delete","p":"payload","pt":"msg"},{"t":"delete","p":"rc","pt":"msg"},{"t":"delete","p":"parts","pt":"msg"},{"t":"delete","p":"strArray","pt":"msg"},{"t":"delete","p":"castTarget","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":420,"wires":[["8d038b77.ebe8e8","ce1430ad.2794e"]]},{"id":"bac40b3f.e56ac8","type":"inject","z":"7b31a85e.379d78","name":"","props":[{"p":"message","v":"This is a test cast.","vt":"str"},{"p":"topic","vt":"str"},{"p":"castTarget","v":"Study Display","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Test Message","payloadType":"str","x":180,"y":480,"wires":[["c15ad04f.c266c"]]},{"id":"dac0804a.613e6","type":"split","z":"7b31a85e.379d78","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":610,"y":420,"wires":[["b69ff338.2498b"]]},{"id":"b69ff338.2498b","type":"change","z":"7b31a85e.379d78","name":"","rules":[{"t":"set","p":"strArray","pt":"msg","to":"$split(payload, ';')\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":420,"wires":[["8f82c7c8.2b82a8"]]},{"id":"8f82c7c8.2b82a8","type":"switch","z":"7b31a85e.379d78","name":"Cast Targets","property":"strArray[9]","propertyType":"msg","rules":[{"t":"cont","v":"'fn='&castTarget","vt":"jsonata"}],"checkall":"true","repair":false,"outputs":1,"x":970,"y":420,"wires":[["dc03a87a.71e0f8","8d038b77.ebe8e8","84e21e46.de69a"]]},{"id":"8d038b77.ebe8e8","type":"debug","z":"7b31a85e.379d78","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1130,"y":460,"wires":[]},{"id":"d6fbebd5.7edfa8","type":"exec","z":"7b31a85e.379d78","command":"avahi-browse","addpay":false,"append":"_googlecast._tcp -rtp","useSpawn":"false","timer":"","oldrc":false,"name":"","x":450,"y":420,"wires":[["dac0804a.613e6"],[],[]]}]

Also note: The process is wrapped in a 2 second loop because sometimes the cast group doesn't show up in the avahi-browse command the first time. It'll just keep retrying until it finds the castTarget you are looking for.

1 Like

That is cool - never considered using NR to search the network for services like that. Usually I provide reserved DHCP's to everything but a residential client of mine has an ISP that does not allow this feature so something like this might be very useful.

Have you tried the node-red-node-discovery node? Seems a little dated but maybe okay.

Yeah, I tried that and attempted to keep a variable up to date. Unfortunately, either the mdns broadcasts didn't happen or the node didn't catch them so I figured a on-demand browse might help. I haven't figured out how to do an mdns resolution for a specific cast group so this'll have to do.

If anyone knows how to do that on cast groups, I'm all ears!

1 Like

Flow for writing HE logs to a DB and sending an alert if the log level is not "info" or "debug"

I created a small flow to write Hubitat logs to a database as I was finding it hard to delve through the native logs. I tacked on the ability to send an SMS/Email based on the log "level".

Below is the basic flow. I am including the code for the nodes outlined in red but PM me if you need the entire flow.

Flow:

[{"id":"36966e59.07b402","type":"websocket in","z":"7b994e31.f24a6","g":"717554fa.f8ae14","name":"Hubitat Log Socket","server":"96044230.8127a","client":"","x":197.6666259765625,"y":2119.333251953125,"wires":[["57aaa540.2a5b84","4cac1755.deddd","9fdfa8df.0fde48"]]},{"id":"57aaa540.2a5b84","type":"function","z":"7b994e31.f24a6","g":"717554fa.f8ae14","name":"Log SQL","func":"var sqlString = 'INSERT INTO LOGS (NAME,MSG,ID,TIME,TYPE, LEVEL)VALUE ('\nvar quote = \"'\"\nvar comma = \",\"\nsqlString +=quote+msg.name+quote+comma\nsqlString +=quote+msg.msg+quote+comma\nsqlString +=msg.id+comma\nsqlString +=quote+msg.time+quote+comma\nsqlString +=quote+msg.type+quote+comma\nsqlString +=quote+msg.level+quote+\")\"\n\n//sqlString = sqlString+quote+msg.name+quote+comma+quote+msg.msg+quote+\",\"+msg.id+\",\"+msg.time+\",\"+msg.type+\",\"+msg.level+\")\"\nmsg.topic = sqlString\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":431.99993896484375,"y":2119.333381652832,"wires":[["c0a6c5c4.10901"]]},{"id":"4cac1755.deddd","type":"debug","z":"7b994e31.f24a6","g":"717554fa.f8ae14","name":"Log Socket Debug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":238.33331298828125,"y":2185,"wires":[]},{"id":"9fdfa8df.0fde48","type":"switch","z":"7b994e31.f24a6","g":"717554fa.f8ae14","name":"Not Info or Debug","property":"level in [\"info\",\"debug\"]","propertyType":"jsonata","rules":[{"t":"false"}],"checkall":"true","repair":false,"outputs":1,"x":474.33331298828125,"y":2181,"wires":[["97cb985e.2d933"]]},{"id":"97cb985e.2d933","type":"change","z":"7b994e31.f24a6","g":"717554fa.f8ae14","name":"Format for SMS/Email","rules":[{"t":"set","p":"message","pt":"msg","to":"msg","tot":"msg"},{"t":"delete","p":"msg","pt":"msg"},{"t":"set","p":"topic","pt":"msg","to":"\"Log: \"&level&\" - \"&name","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"\"Date/Time: \"&time&\"\\n\"&\"Message: \"&message","tot":"jsonata"},{"t":"set","p":"to","pt":"msg","to":"$globalContext(\"rakeshSMS\")&\",\"&$globalContext(\"rakeshEmail\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":721.3333435058594,"y":2181.999885559082,"wires":[["8c34dafb.a6673"]]},{"id":"96044230.8127a","type":"websocket-listener","path":"ws://192.168.1.113/logsocket","wholemsg":"true"}]

Hope this helps someone.

5 Likes

Does anyone have any flows that capture the time stamp? I'm not quite sure how to capture this. I'm looking to capture the timestamp each time my thermostat changes state and put this timestamp into a variable for each "cooling" and "idle" the use the two variables to subtract from one another so that it gives me the last run cycle time.

I am going by memory when I needed to do the same but I think this would work for you to create a Change Node:
image

I don't use it currently.

3 Likes

You can also use node-red-contrib-moment (node) - Node-RED if you want to get the time stamp to be timezone specific. The JSONATA expression also gives the current date/time but it is in UTC.

Here is an example of how the node is configured:

3 Likes

That's the one I use

2 Likes

Is it possible to have that output format just have the time, leaving out the date? Would it work if I remove the date format in it?

I will play with this after my next hvac cycle to see if what I have right now will work or not.

1 Like

Yes - just remove the date part and the output will look like this.

Screen Shot 2021-06-11 at 9.31.38 AM

2 Likes