Node Red: How to start / stop fan at different humidity level bathroom

Hi all,

I have an Aqara temperature and humidity sensor and I want to use it to turn the ventilator on or off. I use Node-Red for most of my automations and it’s very easy to just switch it on when the humidity is above 60 and turn it off when it’s below 60 again.

image

The issue is that to turn the ventilator on soon after the humidity level rises, I need a pretty low value (60 in this example), but it takes very long to reach 60 again and therefore before the ventilator turns off. I’m looking for a way to turn on the ventilator on at for example 60, but turn it off at 70 again. The hard thing in this is that the automation needs to understand if the humidity is dropping or rising, else it will turn on and off between 60 and 70 potentially multiple times.

Does somebody have a good solution for this?

Thanks!
Matthijs

1 Like

I’ve been using this to control a bath fan for about 2 years now with no issues. It uses the statistics platform to keep track of the average (mean) and standard deviation of the humidity level, and only triggers the fan once the humidity rises above the trigger percentage AND rises 5% above the previous humidity reading. It uses 2 global variables to keep track of the previous humidity level and minutes of runtime. This works well to accommodate for varying humidity levels in the house.

sensors.yaml entries for Statistics:

- platform: statistics
    entity_id: sensor.master_bath_humidity_sensor_humidity
    unique_id: sensor.master_bath_humidity_mean
    state_characteristic: mean
    name: master_bath_humidity_mean
    sampling_size : 240
    max_age:
      hours: 48
      
  - platform: statistics
    entity_id: sensor.master_bath_humidity_sensor_humidity
    unique_id: sensor.master_bath_humidity_standard_deviation
    state_characteristic: standard_deviation
    name: master_bath_humidity_standard_deviation
    sampling_size : 240
    max_age:
      hours: 48  

Flow:

[{"id":"07e4c320e8eb0bfb","type":"tab","label":"Master Bath Fan Control","disabled":false,"info":""},{"id":"8ef6fa0b4cbaaf89","type":"server-state-changed","z":"07e4c320e8eb0bfb","name":"","server":"8be923df.d66f9","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.master_bath_humidity_sensor_humidity","entityidfiltertype":"exact","outputinitially":false,"state_type":"num","haltifstate":"","halt_if_type":"num","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":true,"ignorePrevStateUnavailable":true,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":245,"y":105,"wires":[["aa88e46d6cbf50a4"]]},{"id":"1645a616194978dd","type":"rbe","z":"07e4c320e8eb0bfb","name":"only pass changes","func":"rbe","gap":"5","start":"","inout":"in","property":"current","x":150,"y":165,"wires":[["4c756ec0f0161cf0"]]},{"id":"5b717be902594021","type":"api-call-service","z":"07e4c320e8eb0bfb","name":"Turn Fan On","server":"8be923df.d66f9","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.shelly_master_bath_fan"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":115,"y":285,"wires":[["37eb391466852787"]]},{"id":"92796e4c9b2cad8c","type":"function","z":"07e4c320e8eb0bfb","name":"log message Fan on","func":"msg.payload=\"Fan ON for \" + msg.duration + \" min - Cur: \" + msg.current + \" Prev: \" + msg.prev + \" Avg: \" + msg.mean + \" StdDev: \" + msg.stddev + \" Trigger: \" + msg.trigger;\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","x":430,"y":300,"wires":[["68585e97cd6ef104"]]},{"id":"68585e97cd6ef104","type":"api-call-service","z":"07e4c320e8eb0bfb","name":"","server":"8be923df.d66f9","version":5,"debugenabled":false,"domain":"logbook","service":"log","areaId":[],"deviceId":[],"entityId":[],"data":"{\"name\":\"Master Bath Humidity Sensor\",\"message\":\"{{payload}}\",\"entity_id\":\"sensor.master_bath_humidity_sensor_humidity\",\"domain\":\"sensor\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":415,"y":360,"wires":[[]]},{"id":"e2ae5a304f311291","type":"api-call-service","z":"07e4c320e8eb0bfb","name":"Turn Fan Off","server":"8be923df.d66f9","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.shelly_master_bath_fan"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":100,"y":390,"wires":[["d8726de281d29653","6a7f7dabd8541ffa"]]},{"id":"0f387780b5b12a19","type":"function","z":"07e4c320e8eb0bfb","name":"log message FAN OFF & reset duration to 4 min","func":"// reset default fan duration\nglobal.set(\"var_master_bath_fan_duration\", 4);\n\n// msg.elapsed.time.minutes comes from the Hourglass node\nmsg.payload=\"Master Bath Fan OFF after \" + msg.elapsed.time.minutes + \" min - Cur: \" + msg.current + \" Avg: \" + msg.mean + \" StdDev: \" + msg.stddev + \" Trigger: \" + msg.trigger;\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":285,"y":525,"wires":[["68585e97cd6ef104","dc7c4eab3a874b13"]]},{"id":"f7cde13af83e72b0","type":"comment","z":"07e4c320e8eb0bfb","name":"1 - Master Bathroom Moisture Level","info":"","x":155,"y":30,"wires":[]},{"id":"9dcb5ac5efd6aaa1","type":"inject","z":"07e4c320e8eb0bfb","name":"Report Current values","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":600,"wires":[["aedd134b138409a0"]]},{"id":"cbfc4cc28485c70c","type":"debug","z":"07e4c320e8eb0bfb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":520,"y":735,"wires":[]},{"id":"4e51b6c3185c3fe2","type":"function","z":"07e4c320e8eb0bfb","name":"Get average & std deviation over last 48 hours","func":"// get previous humidity reading - default to \n// current reading if not available\nvar previous_humidity = global.get(\"var_master_bath_humidity_previous\");\nvar duration = global.get(\"var_master_bath_fan_duration\")||3;\n\nvar trigger=msg.mean + (msg.stddev/2);\ntrigger=Math.round(trigger);\nmsg.payload= \"cur=\" + msg.payload + \" prev=\" + previous_humidity + \" mean=\" + msg.mean + \" stddev=\" + msg.stddev + \" trigger=\" + trigger + \" duration=\" + duration;\nreturn msg;\n\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":735,"wires":[["cbfc4cc28485c70c"]]},{"id":"2b951da1e91e521c","type":"function","z":"07e4c320e8eb0bfb","name":"Determine if trigger has been reached","func":"// get previous humidity reading - default to \n// current reading if not available\nmsg.prev = global.get(\"var_master_bath_humidity_previous\"||msg.current);\nmsg.prev=Math.round(msg.prev);\nglobal.set(\"var_master_bath_humidity_previous\", msg.current);\n\nmsg.trigger=msg.mean + (msg.stddev/2)\nmsg.trigger=Math.round(msg.trigger);\n\nif (msg.current >= msg.trigger && msg.current >= (msg.prev + 5.0)) {\n\n   msg.duration = global.get(\"var_master_bath_fan_duration\")||4;\n\n  if (msg.duration>29) {\n   // don't go over 30 minutes\n   return null;\n} else {\n   global.set(\"var_master_bath_fan_duration\", (msg.duration + 4));\n   return msg;\n}\n\n   } else {\nreturn null;\n}\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":465,"y":225,"wires":[["92796e4c9b2cad8c","5b717be902594021","b7804db14e183b02"]]},{"id":"b457010bc8fee662","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get Current Humidity","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_sensor_humidity","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":540,"y":680,"wires":[["4e51b6c3185c3fe2"]]},{"id":"d8726de281d29653","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get Current Humidity","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_sensor_humidity","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"current","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":205,"y":450,"wires":[["f6c414a431bc4002"]]},{"id":"ae0b768c35f7e367","type":"inject","z":"07e4c320e8eb0bfb","name":"Reset duration to 3 min","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":175,"y":825,"wires":[["b7fb77fd982decca"]]},{"id":"b7fb77fd982decca","type":"function","z":"07e4c320e8eb0bfb","name":"Reset duration to 3 min","func":"\n   global.set(\"var_master_bath_fan_duration\", 3);\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":825,"wires":[[]]},{"id":"aa88e46d6cbf50a4","type":"change","z":"07e4c320e8eb0bfb","name":"Set msg.current","rules":[{"t":"set","p":"current","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":100,"wires":[["1645a616194978dd"]]},{"id":"572e2c8484aa5a88","type":"hourglass","z":"07e4c320e8eb0bfb","name":"runtime","persistId":"12345","humanizeLocale":"","x":660,"y":375,"wires":[["0f387780b5b12a19"]]},{"id":"b7804db14e183b02","type":"change","z":"07e4c320e8eb0bfb","name":"start","rules":[{"t":"set","p":"command","pt":"msg","to":"start","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":330,"wires":[["572e2c8484aa5a88"]]},{"id":"6a7f7dabd8541ffa","type":"change","z":"07e4c320e8eb0bfb","name":"stop","rules":[{"t":"set","p":"command","pt":"msg","to":"stop","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":435,"wires":[["572e2c8484aa5a88"]]},{"id":"f6c414a431bc4002","type":"change","z":"07e4c320e8eb0bfb","name":"status","rules":[{"t":"set","p":"command","pt":"msg","to":"status","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":480,"wires":[["572e2c8484aa5a88"]]},{"id":"dc7c4eab3a874b13","type":"change","z":"07e4c320e8eb0bfb","name":"reset","rules":[{"t":"set","p":"command","pt":"msg","to":"reset","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":525,"wires":[["572e2c8484aa5a88"]]},{"id":"37eb391466852787","type":"stoptimer3","z":"07e4c320e8eb0bfb","duration":"4","durationType":"num","units":"Minute","payloadtype":"num","payloadval":"0","name":"","x":110,"y":345,"wires":[["e2ae5a304f311291"],[]]},{"id":"44ce9b498d0db448","type":"inject","z":"07e4c320e8eb0bfb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":880,"wires":[["eac206591ef83323"]]},{"id":"f2e8224b6161890a","type":"debug","z":"07e4c320e8eb0bfb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"stddev","targetType":"msg","statusVal":"","statusType":"auto","x":555,"y":875,"wires":[]},{"id":"eac206591ef83323","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get stats - stddev","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_standard_deviation","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"stddev","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":310,"y":880,"wires":[["f2e8224b6161890a"]]},{"id":"4c756ec0f0161cf0","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get stats - stddev","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_standard_deviation","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"stddev","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":390,"y":160,"wires":[["fdf56ee326a6a3d1"]]},{"id":"fdf56ee326a6a3d1","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get stats - mean","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_mean","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"mean","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":580,"y":160,"wires":[["2b951da1e91e521c"]]},{"id":"aedd134b138409a0","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get stats - stddev","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_standard_deviation","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"stddev","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":130,"y":660,"wires":[["3ac0985ea891f10b"]]},{"id":"3ac0985ea891f10b","type":"api-current-state","z":"07e4c320e8eb0bfb","name":"Get stats - mean","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.master_bath_humidity_mean","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"mean","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":320,"y":660,"wires":[["b457010bc8fee662"]]},{"id":"8be923df.d66f9","type":"server","name":"homeassistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":""}]
3 Likes

I have other issues with HA at the moment, but will try this solution for sure when I have everything running again! Thanks

I have everything running as intended again and tried your solution. I run into the issue that you have some node types that I don’t have, what typesare they and how can I add them?

Click on the 3 bars on the top-right of Node Red and select “Manage Palette”. Select the Install Tab and type in the name of the node (stoptimer3 and hourglass) and click Install.

Any adjustments will be made in the function labeled “Determine if trigger has been reached”. The entry “(msg.prev + 6.0)” means that the humidity must rise 6% above the previous value and the entry “(msg.duration + 4)” means that it will add 4 minutes to the amount of time the fan stays on. You can make adjustments to those 2 numbers to tweak how quickly the fan turns on and how long it stays on. I’m using a Shelly 1 that also has a built-in Timer that I’ve set to turn off the fan after 30 minutes no matter how many minutes Node Red turns it on for.

1 Like

image

you can create a sensor to use as a condition/trigger or plainly use this in your flow, whatever… This way you’ll distinguish whether it’s rising or dropping.

You want to turn the ventilator on at 70% and then off at 60%? I don’t quite get your explanation…

Thanks Mightybosstone, I could’ve figured that out myself. Let’s see if this works!

Obaldius: I want to turn the fan on at a lower value (e.g. 60), so that it turns on quickly. Then I want it to turn off at a higher value (e.g. 70), to prevent it from running very long.

Make sure you’ve set up the statistics on your humidity sensor long enough beforehand (several days) so that it can have a good value for the mean and std deviation. The beauty of this approach is that you don’t need to care about the actual humidity level (60%, 70%, etc). You’re only concerned with having it trigger when it raises above the norm, and it only adds run-time while the humidity is increasing and stops adding minutes as soon as the humidity drops.

1 Like

FYI, there is a new helper introduced (in the latest HA release 2022.4.5) that measures the derivative (dx/dt). i.e. it measure the rate of change of a measurement with respect to time. Since humidity fluctuates depending on the time of the year (relatively slowly), measuring on the derivative provides large fluctuations in humidity for the sensor being measured and therefore can provide a trigger for your fan to turn ‘on’ and subsequently 'off ’ as the derivative turns negative.

Helpers can be found ‘Configuration’ → ‘Automations & Scenes’ → ‘Helpers’ → ’ Add Helper’ → ‘Derivative Helper’

1 Like

Thanks, I made a derivative sensor, let’s see how that works out.

I had this flow disabled as we were on holiday, just enabled it. Let’s see how this works out.

The master_bath_humidity_mean and -standard_deviation are Unavailable though, should I just wait or did I something wrong?

Did you set up your 2 - platform: statistics in sensors.yaml and restart? One for the mean and one for the standard deviation.

Thanks bastero for pointing out the new derivative integration! I build a new flow based on it and it seems to be working just as well as using the mean/std deviation method, with much less code and complexity. I’ll post that code in a bit.

1 Like

Here’s an alternate flow to control the bath fan based on the new derivative integration that bastero mentioned. I’ve been testing it by just logging the start and stop times, and it seems to work as expected.

For the derivative sensor I used a time window of 00:00:00 and a time unit of ‘minutes’. In theory it should only trigger when the derivative value rises or drops below zero, but I found that it sometimes would bounce to a value of positive 1, so I set the switch to turn on when the value is >=2.

[{"id":"fcb3c47492902266","type":"tab","label":"Bath Fan Control","disabled":false,"info":"","env":[]},{"id":"2ad8bfddd3944e76","type":"server-state-changed","z":"fcb3c47492902266","name":"Master Bath Humidity","server":"8be923df.d66f9","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.master_bath_humidity_testa","entityidfiltertype":"exact","outputinitially":false,"state_type":"num","haltifstate":"","halt_if_type":"num","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":true,"ignorePrevStateUnavailable":true,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"humidity","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":160,"y":100,"wires":[["975a3edb4b829a46"]]},{"id":"975a3edb4b829a46","type":"switch","z":"fcb3c47492902266","name":"+ or -","property":"humidity","propertyType":"msg","rules":[{"t":"gte","v":"2","vt":"num"},{"t":"lte","v":"0","vt":"num"}],"checkall":"false","repair":false,"outputs":2,"x":330,"y":100,"wires":[["5f1f208fe0d412e2"],["e23d2b9b09892744"]]},{"id":"5f1f208fe0d412e2","type":"function","z":"fcb3c47492902266","name":"log message Fan on","func":"var Time = new Date();\nmsg.payload=\"Fan ON \" +  msg.humidity + \"%\";\n\nflow.set(\"var_master_bath_fan_start_time\", Time);\n   \nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":100,"wires":[["640cce28efe28e3b"]]},{"id":"62f095e952acf380","type":"function","z":"fcb3c47492902266","name":"log message Fan off","func":"var Time = new Date();\nvar stop_time = flow.get(\"var_master_bath_fan_start_time\");\nvar duration =(Time - stop_time)/1000;\nduration=Math.ceil(duration*100)/100;\nduration=Math.ceil(duration/60);\nmsg.payload=\"Fan OFF \" +  msg.humidity + \"% \" + duration + \" min\";\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":280,"wires":[["640cce28efe28e3b"]]},{"id":"640cce28efe28e3b","type":"api-call-service","z":"fcb3c47492902266","name":"","server":"8be923df.d66f9","version":5,"debugenabled":false,"domain":"logbook","service":"log","areaId":[],"deviceId":[],"entityId":[],"data":"{\"name\":\"Master Bath Humidity Sensor TEST\",\"message\":\"{{payload}}\",\"entity_id\":\"sensor.master_bath_humidity_sensor_humidity\",\"domain\":\"sensor\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":970,"y":160,"wires":[[]]},{"id":"e23d2b9b09892744","type":"api-current-state","z":"fcb3c47492902266","name":"Get Fan Status","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"switch.shelly_master_bath_fan","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","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":520,"y":160,"wires":[["982ed164b76de56b"]]},{"id":"982ed164b76de56b","type":"switch","z":"fcb3c47492902266","name":"Fan On or 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":520,"y":220,"wires":[["62f095e952acf380"],[]]},{"id":"24047622b15b3d4a","type":"comment","z":"fcb3c47492902266","name":"Turn Fan switch ON Here","info":"","x":810,"y":120,"wires":[]},{"id":"3fdb0c9275dbd467","type":"comment","z":"fcb3c47492902266","name":"Turn Fan switch OFF Here","info":"","x":770,"y":220,"wires":[]},{"id":"8be923df.d66f9","type":"server","name":"homeassistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":""}]
3 Likes

Hi. Where in your flow are you specifying the derivative value? I guess if you can let me know what you called it i can find it.

Create an entity/helper in Home Assistant: Settings - Devices and Services - Helpers - Create Helper.

I’m getting an error when deploying the flow. It is:

The workspace contains some nodes that are not properly configured:

  • [Bath Fan Control] log message Fan off (function)

Not sure where to start since I haven’t played with logs before. I really appreciate any help you can provide.

One of the updates to Node Red caused me to change the way I was getting the current time so I could calculate the duration. Change the following in each of the functions and see if that works:

Change from:

var Time = new Date();

To:

var Time = new Date().valueOf();

Also change the variable name stop_time to start_time at both locations in the second function as that is actually the time the fan was started and the flow variable populated.

That cleared out the errors on deployment, thanks! I’ll keep running it. Thanks for sharing the flow!

I’m somewhat confused by this. You’re actually reading the rate of change of the humidity to trigger the automation, right? When I run the fan, the humidity immediately starts dropping rapidly, even with the shower running, and if I understand this logic correctly it will shut off immediately.

Also, wouldn’t this automation shut off the fan if, for example, someone turned it on manually, if the humidity was dropping for any reason at all? I’m going to run this through some trials shortly, but I must admit some confusion. I feel like the state machine needs to be a little more complicated for this to work. Are you running it in production yet? Or still testing?