Checking a tumble dryer for its "Anti Crease" state

Hi,

I recently managed to get Home Assistant setup with Zigbee and Node Red.
Now I am overwhelmed with what you can do. A thing that I wanted to do for a long time is sending a message when our tumble dryer reached its "anti crease" state (=finished).

I googled for hours an watched a ton of tutorials but programming somethig seemingly will never be my bag.

I do need a "trigger" so that would be the Power channel of my Zigbee Plug. But now I am at a loss:
I would need some form of evaluation of the values that come through to determine the state and send a message. I manages to get the latter part running by watching tutorial videos. So I can already send a message to my phone. Check. But I have no clue how to evaluate/compare the power values from my plug in Node Red. The issue here is the "anti crease" phase. Please see this screenshot of a diagram.

I cut the image off right when the repetitive part of the drying process comes.
The "off" 0 Watt phase is 25 seconds long the "on" phase in most cases is 5 seconds long.
I cannot switch the anti crease off so I would like to find a way to analyse when this phase has come.

As it seems I am lacking a real grasp of how to construct something like this with the nodes respectively the logic thinking behind the project.

I tried it with a additionally downloaded "power monitor" node

but the thing is that when I set values there it will be triggered during the regular drying phase as the dryer will start and stop multiple times. So I thought there must be a way to analyse it otherwise.

Could someone please help me here. Maybe it is simpler than I thougt. I wanted to solve it myself but after several day it is getting frustrating. I hope the description is understandable as English is not my first language.

Best Regards
Stefan

Welcome @CountDocula

It looks and would seem probable that the Anti-crease mode operates the drum at a regular frequency. Perhaps...

Could you not use a trigger node with a function node to see when/how often this activates as a regular current draw and if the timing can be seen as regular and within certain parameters, classify as 'Anti-crease mode'?

mudwalker, thank you for your input. This approach may/will work but from what I saw in the tutorials the function nodes must be programmed. This is the first big problem for me, I can understand and, to an extend, adapt simple code for my purposes but I lack the ability to create that on my own.

I know that the anti-crease mode must somehow be identified and processed but that is exactly where I am stuck. For me all that poses a steep learning curve and currently it is mostly copying and adapting the simplest examples. I am far from having the knowledge to make such a thing on my own. Thought it would be easiser but I guess that one needs to continue and not give up.

Hi CountDocula, welcome to Node-red.

You are using HomeAssistant, which from what I can see puts a layer of extra software between you and the smart plug.
Most of the folk here prefer using just Node-red because it lets us more directly interact with the devices.
However, a benefit of Home Assistant seems to be the very nice power consumption graph you posted.

I guess that one way you can identify the anti-crease phase might be:

  • The power is on,
  • 10 seconds later it is off again.
  • This sequence repeats. Let's say 3 repeats confirms anti-crease

If it was pure Node-red I'd say you have to poll the plug every (about) 3 seconds to be sure of catching the ON pulse.
What is the equivalent in HA? How can Node-red obtain the power every 3 seconds?

I am busy today, but I can take a look tomorrow. I might be able to work something out, but must admit that my coding is 'OK', but not great!!

You say power is on every 10 seconds (let's say), there seems to be a decay over several 'cycles' and the current always exceeds ~75W.

How long is it on for?

These parameters are needed to be able to work out 'what is physically going on'.

To get a better feel, I recommend watching this playlist: Node-RED Essentials. The videos are done by the developers of node-red. They're nice & short and to the point. You will understand a whole lot more in about 1 hour. A small investment for a lot of gain.

Sorry, if you have any NR flow (even the bit that you can see the Current reading on) can you post it please? We can then talk the same language. We need to be able to see how the values are available to NR

In order to make code readable and usable it is necessary to surround your code with three backticks (also known as a left quote or backquote ```)

``` 
   code goes here 
```

You can edit and correct your post by clicking the pencil :pencil2: icon.

See this post for more details - How to share code or flow json

@jbudd
you are correct in your assumptions.
I run home assistant in a VM on an Unraid system. I installed zigbee2mqtt as well as Mosquitto broker for MQTT.
I stumbled upon Node Red while working myself into home assistant, which I started some 3 weeks ago.
Before I had nothing to do with all that so please forgive my lack of knowledge.

Your detection "ruleset" is correct apart from the values. The ON time is always 5 seconds (apart from that staircase step down (or whatever one could call it) which is 5 seconds at high Watts and 5 seconds at lower Watts, followed by the 25 second interuption.
I have not tried that with the HA as I was just starting and according to the videos I watched Node Red offers a wider functionality (oh yes, it does!)
What I used in Node Red to start off with is the events: state node which seems to get the values quite nicely.

@mudwalker
The "cycle" seems to consist of 7 different power peaks of which the 6th one is different.
Always 25 Seconds at 0 Watts
6 of the 7 power peaks: 5 seconds at different Power levels
1 of the 7 power peaks: 5 seconds at high power + 5 seconds at lower power.
Then "rinse and repeat"

Please see a Screenshot of another dryer run (complete)

And a zoomed in version of the anti-crease cycle

What I have as flow is that (I used the power monitor and the injections nodes to test if the mobile phone message would work... sorry, all in German)

[{"id":"1e54067cd59ed0c8","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"36db2f05fb5d60a6","type":"server-state-changed","z":"1e54067cd59ed0c8","name":"Leistungsprofil_Trockner","server":"ef342384.10774","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.0xa4c138632015ebf4_power","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":190,"y":140,"wires":[["b89f90378ffd2eb9"]]},{"id":"b89f90378ffd2eb9","type":"power-monitor","z":"1e54067cd59ed0c8","name":"Trockner ","startthreshold":"20","stopthreshold":"20","startafter":1,"stopafter":1,"energydecimals":4,"emitidle":false,"x":460,"y":140,"wires":[["6859fe2f6ca6958d"]]},{"id":"6859fe2f6ca6958d","type":"switch","z":"1e54067cd59ed0c8","name":"Event?","property":"payload.event","propertyType":"msg","rules":[{"t":"eq","v":"start","vt":"str"},{"t":"eq","v":"running","vt":"str"},{"t":"eq","v":"stop","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":620,"y":140,"wires":[[],[],["3561ddd7a9a6cef0"]]},{"id":"3561ddd7a9a6cef0","type":"function","z":"1e54067cd59ed0c8","name":"Android Message erstellen","func":"msg.payload.time = Math.round(msg.payload.time / 60);\nmsg.payload.cost = Math.round(msg.payload.energy * 45) / 100;\nmsg.payload = { \"data\": { \"message\": msg.payload.name + \" ist fertig! Gesamte Zeit: \" + msg.payload.time + \" Minuten. Verbrauch: \" + msg.payload.energy + \" kWh. Kosten: \" + msg.payload.cost + \" €\", \"title\": \"Wichtige Nachricht aus dem Keller!\", \"data\": { \"group\": \"Wäschestatus\" } } };\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":860,"y":140,"wires":[[]]},{"id":"ab063c6aaf7d5321","type":"inject","z":"1e54067cd59ed0c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"50","payloadType":"num","x":190,"y":340,"wires":[["b89f90378ffd2eb9"]]},{"id":"d65bd0c896dd6edd","type":"inject","z":"1e54067cd59ed0c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":190,"y":400,"wires":[["b89f90378ffd2eb9"]]},{"id":"ef342384.10774","type":"server","name":"Home Assistant","addon":true}]

Thank you by the way for the tip regarding tutorial videos. I will go through them as well.
I will also try the Open AI chatbot. A friend hinted me to that.
Maybe I will not be able to respond to quickly in the next days as I am pretty busy.

Thank you guys very much so far. Great help. I will post, should I be able to find a way to the goal.

So, I cannot identify the first couple of nodes for input from your flow, assume that are from Home Assistant.

But, I do have a flow that will trap 5 events of 4.9 - 5.1 seconds with a difference >+120W change in readings from the input. If your device outputs to MQTT, you could get the input from there. If you aren't sure of the message from MQTT try using MQTT Explorer, you should be able to work out the message topic from the Plug from that.

The flow uses all standard Node-RED nodes except for @BartButenaers node-red-contrib-interval-length which you can download through Manage palette in the RHS menu (assuming you can still do this through HA).

The Inject and Trigger nodes I have used to send an approximated waveform of your input. I would guess that the described conditions will not occur anywhere else in the Washing cycle.

[{"id":"56bbecb2b225bf25","type":"debug","z":"1e54067cd59ed0c8","name":"debug 14","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":560,"y":420,"wires":[]},{"id":"bd4759edb3f07913","type":"interval-length","z":"1e54067cd59ed0c8","format":"mills","bytopic":false,"minimum":"4900","maximum":"5100","window":"","timeout":false,"msgTimeout":"400","minimumunit":"msecs","maximumunit":"msecs","windowunit":"msecs","msgTimeoutUnit":"msecs","reset":false,"startup":false,"msgField":"payload","timestampField":"timestamp","repeatTimeout":false,"name":"","x":580,"y":460,"wires":[["c36c551c912b3102"],[]]},{"id":"2b2b3a78fcd30c3e","type":"debug","z":"1e54067cd59ed0c8","name":"debug 15","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":460,"wires":[]},{"id":"c36c551c912b3102","type":"function","z":"1e54067cd59ed0c8","name":"5 ~5s events","func":"let count = 5;  //number of events condifered to qualify as anti-crease\nlet currentCount = flow.get('currentCount')||0;\n\nif (count - currentCount <= 0){\n    msg.payload = \"Anti-crease\";\n    //Carry out required action\n    flow.set('currentCount', 0);\n    msg.count = currentCount;\n}\nelse \n{ \n    msg.payload = \"NOT Anti-crease\";\n    //Carry out required action, or not if you want to let be.\n    currentCount++;\n    flow.set('currentCount', currentCount);\n    msg.count = currentCount;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":460,"wires":[["2b2b3a78fcd30c3e"]]},{"id":"2c6181b1be5e6ce6","type":"group","z":"1e54067cd59ed0c8","name":"Waveform from plug (MQTT?)","style":{"label":true},"nodes":["9fea62c7cd59d9c7","2a21c8cc1113dedc","1b8462f28d4c9f02"],"x":74,"y":359,"w":372,"h":142},{"id":"9fea62c7cd59d9c7","type":"mqtt in","z":"1e54067cd59ed0c8","g":"2c6181b1be5e6ce6","name":"","topic":"stat/Radio/RESULT","qos":"2","datatype":"auto-detect","broker":"a89a670e2bb67b92","nl":false,"rap":true,"rh":0,"inputs":0,"x":290,"y":400,"wires":[[]]},{"id":"2a21c8cc1113dedc","type":"inject","z":"1e54067cd59ed0c8","g":"2c6181b1be5e6ce6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":460,"wires":[["1b8462f28d4c9f02"]]},{"id":"1b8462f28d4c9f02","type":"trigger","z":"1e54067cd59ed0c8","g":"2c6181b1be5e6ce6","name":"","op1":"120","op2":"0","op1type":"num","op2type":"num","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":360,"y":460,"wires":[["56bbecb2b225bf25","bd4759edb3f07913"]]},{"id":"a89a670e2bb67b92","type":"mqtt-broker","name":"Node-RED MQTT","broker":"172.27.123.58","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

I hope that this will help at least a bit, but I don't use HA, so as I say, some guesses!!

*I have not trapped the 30secs between the anti crease pulses, didn't see the need at this stage.

2 Likes

mudwalker,
impressive! Thank you!!
Never I would have been able to come up with something like that. I managed to import it all. Said node I had already installed. It works and the debug shows all the values and messages. Now I just need to adopt to my setup. The action I would like to take when the cycles are detected (after 5 in your example) is that I want so send a message to a mobile phone. I have some code for that. Once everything is set up I will try to combine the solution. I guess the function node needs to have a certain output. But I do not want to add more confusion...

I am still trying to figure out which node to start it all with... the "trigger". I was on the wrong track as is seems. I used the events:state node (node-red-contrib-home-assistant-websocket) as I saw it being used in some tutorials.

You are correct that there are nodes from Home Assistant. Now I have learned that this is not the standard.Good to know.

I basically have an entity from my power plug that delivers the power value in Watt. If I understood correctly then the MQTT in node would be the way to go? Sadly I do not manage to get connection to my localhost Mosquitto server. I will have to look into that as it seems. Thanks again so far for taking the time to help me!

I have made comments in the function node where you need to add your 'command' to trigger the sending of a message. You should be able to add what you need from the HA messages (just add your Switch Node and Message Node?). Can't see what actual messages are without HA and your setup.

That box with the Inject Node, Trigger Node and MQTT Node are so that I could try to imitate your waveform. You need to input your Power Value through msg.payload to the Interval Trigger, or change whatever message your Current Power is on to msg.payload (Change Node?).

HA is very popular with a lot of support, but as @jbudd says, it adds a middle layer between NR and the device, which is fine, but many here prefer to talk direct to the device and usually, in these types of devices, through MQTT. You say 'entity', I have no idea what that is, presumably how the data is presented for NR consumption. I get my data raw from the device.

You send your messages through SMS, I send mine via Telegram. At the end of the day, we use what we are comfortable with. There is a learning curve with any system, mine was to learn NR (and I am still a novice at writing Javascript). With my background I can 'see' the logic, so have to find the JS instructions to suit and so NR suits me fine.

You have to choose your own path, the one you feel comfortable with. Of course, others may have come up with a completely different flow to solve this problem, but, this is how I would do it (subject to field testing!).

Read that link I sent, it really is worth it and if you feel that this has done enough for you, please mark as 'Solution' so that others know.

1 Like

@mudwalker Thank you so much for your kind support and especially the explanations. I am still not where I want to be, knowledge-wise. So I will dig deeper into the matter and see "what does what". Until now the conversation with you for me was a real eye-opener as I learned that NR can be used with or without HA.
Seemingly there are some differences as the whole entity matter is not used outside HA (or it is called differently).

I will leave the topic open until I got where I want to be and present a solution resp. report back. I will look into yours first and try to learn what I need to do to make it work with the setup I have.
By the way, I have always envied people with the "third eye" (programming-wise) I do not have it and I guess that adds a lot to the learning curve.

I will check the link and videos.

Thanks for your time and patience and for the insights!!! This gives me solid ground to work on.

1 Like

Managed to get it done using a lot of sources and trial and error. The message is sent when the 0 W phase (25s length) is detected 4 times. All one needs to add at the end is a call service node (HA specific) with the mobile phone that shall receive the message.

Something I not manged to get done is the duration info in the message but that I will do sometime in the future.

[{"id":"8332a4d6a1af9a59","type":"function","z":"aa3ad9cb93399987","name":"Android Message erstellen","func":"if (msg.payload === \"Dryer finished!\") {\n    msg.payload.time = Math.round(msg.payload.time / 60);\n    msg.payload.cost = Math.round(msg.payload.energy * 45) / 100;\n    msg.payload = { \"data\": { \"message\": \"Dryer is finished! Duration: \" + msg.payload.time + \" Minuten. Verbrauch: \" + msg.payload.energy + \" kWh. Kosten: \" + msg.payload.cost + \" €\", \"title\": \"Message from the dryer room!\", \"data\": { \"group\": \"Wäschestatus\" } } };\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":140,"wires":[[]]}]

Maybe someone may benefit from that.

2 Likes