Smart Laundry Example


Smart Laundry

  • Requires 2 Energy Monitoring Outlets (Zooz ZEN15 or similar)
  • Optional: 2 contact sensors.

Provides Washer/Dryer alerts and reminders.

I often forget a wet load of laundry and this is my solution. Seems to work flawlessly with my washer/dryer though the energy-saving timeout on my dryer is about 1minute, so the dryer cycle complete doesn’t trigger for ~1 minutes after the actual end of the cycle.

Tells you how long things took and how long it took you to start a dryer cycle after the wash cycle was complete.

This piston would not work well for those who air dry clothes (y’all are A+ citizens). An escape loop for air-dry cycle would need to be made, either with a button press or using the contact sensor for opening the washing machine.

Messages are stored in a variable before the push notifications are made. This is so that a user could add an additional SMS notification if desired and use the same {message} variable.

Global variables are used so that other pistons in my house can use their data (such as my house ‘go to bed’ piston warning me if I go to bed with a pending laundry load)

Global Variables:

boolean: @dryer_started
datetime: @dryer_started_at
datetime: @dryer_completed_at
boolean: @washer_started
datetime: @washer_started_at
datetime: @washer_completed_at
boolean: @wet_laundry

Washer Cycle Start: [zmck8]

Washer Cycle End: [r65r]

Dryer Cycle Start: [wmes]

Dryer Cycle End: [oj3yq]

Laundry Reminders: [n2va2]


Hello, and welcome to the club!

I love your concept here, but many potential issues stand out to me.
(would you be interested in feedback?)


Fore sure. I’ve ran it through a couple times as segmented pistons (one piston per root IF statement) and it worked well. I’m sure it can be made better though.


My time is a bit short at the moment, but here’s a quick summary of issues you can expect:

  • This piston has at least 16 triggers(with each running thru the piston top to bottom)
  • Normally, two triggers cannot be true at the same moment. (lines 78 & 80… 86, 88, 94 & 96)
  • 2 of the triggers are power based… (expect non-stop action)
  • 8 of them are time based… (expect heavily overlapping timers)
  • 6 of them are based on @global changes… (which only updates after the piston has completed)
    This means each run with a @global change uses old data for the remainder of the execution

If you turn your Logging level to Full, you will see what I am talking about.
(which will be even worse with parallelism enabled)

For reference:

  • I try to keep a single trigger per piston.
  • I always keep “STAYS” triggers separate
  • I am reluctant to use power as a trigger
  • I avoid multiple timers running concurrently in the same piston
  • I never set a @global, and then expect the next block to see that new data
    (local variables work well for this)
  • Parallelism is rarely the solution… especially in an over crowded piston

To be honest, there are simply too many factors in play to share a quick solution incorporating all of these…


In case you were unaware… let’s take a quick look at your first trigger:


The piston will run thru the entire code (top to bottom) at each and every change to power.
(no matter how small)

Outlet 3's power changes to 0.1W
Outlet 3's power changes to 0.2W
Outlet 3's power changes to 0.3W
Outlet 3's power changes to 100W

… will all run thru the entire piston, and execute anything not blocked by conditions

This gets worse when we consider that many devices report power changes dozens of times each minute! (often, even if the device is not being used)


Makes sense, thanks. I originally had each root IF statement as a separate piston. I just put them together for easy export. I’ll separate them again and share each.


This appears to be useful only with a gas dryer. An electric dryer requires 240VAC, and I am not aware of any 240VAC smart outlets. (If anybody knows of one that works with a 4-prong dryer cord, please reply.)


Firstly, thanks! I separated the pistons back into their separate phases.

My thought process on some other points to reference, and some philosophy on optimization:

I am going to continue using the power subscription method for the piston to control the logic of my laundry routine. Namely, if the SmartThings platform can’t handle this type of execution than they really are a poor play in this market. Booleans of laundry started should prevent too much of the logical block to be executed when those segments are not needed and a power report is generated.

Min-maxing the piston based on server load is a concern for me if for instance it creates an undo stress on an individual or an end-users experience with SmartThings… however if it’s just to maximize the economic enrichment of Samsung, I could care less.

For instance, my hypothesis is that if one were to use this series of pistons to save them on one single re-wash of a clothes wash cycle having left their clothes wet for too long, they will have paid back earth in energy expenditure for many years against the efficiency of running the logic on Samsung servers.

I checked the idle state of my monitoring switches to see if logic blocks would be ran unjustly, and determined that the product I have does not cause pistons to run when energy is not drawn:

Last device report:

13 hours ago( DEVICE power 0.0 Washing Machine power is 0.0 W

The efficiency of these logical segments against power reports even 24/7 could easily be ran on a raspberry pi 3 (5w of compute power) without it noticing. The only reason I don’t go that route with OpenHAB is because I would rather write code for end users than write code for a contractor to sell my product to their end user.


You could put one of these into your mains power box for your electric dryer so long as your dryer is wired similar to US reg that it must have it’s own dedicated circuit. (I’m guessing that’s the case)

Aeotec Home Energy Meter:

They are pretty cost prohibitive though. My solution might be to use the energy monitoring on the washer, but edit the dryer cycle IF statements to use a vibration sensor attached to the clothes dryer instead of using power data.

If you want, I can put together a quick example of the dryer segment using a vibration sensor.


ST can handle power triggers, but us, the users, can unknowingly create code that could have a major impact on many things.

Quick summary: IMO, if a piston has a “power” trigger, then it needs to have very lean code.
(IE: run top to bottom in under a second)

With power triggering often thousands of times each day… I doubt the savings are even a fraction of that. (although your goal is very noble)

The proper way to test this is to turn Logging level to Full on this piston, and let it run.
(Don’t use ST to determine what is seen by webCoRE. Use webCoRE)


Lol seriously? No. Consider a raspberry pi running on 5w of power could handle many times the stream of data at 5w thousands per day? It could handle hundreds of thousands of these IF statements on 5w… consider playing minecraft on the pi without issues. Lets pretend it uses ALL the power it consumes to run the data stream. That is waaay exaggerated but that gives you the benefit. That’s ignoring the fact that it actually runs on a server machine which will be much more efficient.

5*24 = 120w or .12kWh per day. 43.8kWh per year to run the entire thing. That’s the logic that runs OpenHAB, and all of the logic that OpenHAB as to process from data packets from a z-wave stick.

In practice, OpenHab uses about 7% of the CPU overhead of a rasberry pi4… so you still have over 90% CPU power to do whatever you want with… 43.8kWh would be if the pi ran at 400% load all year, which it wont… it will run at around 7%… but OK… let’s just go for it.

My washer runs at about .5kWh per use… for electricity alone, which represents about 10% of the power it takes to run, 90% of the energy of a wash is used on water heating and treatment… not agitation and valve opening. So… back of the napkin math brings our energy use to 5kWh per wash including heat energy… I’ll give you the energy for the soap for free.

So 1 year of running ALL HA automation (not just this piston) = 43.8kWh… Let’s call it 50kWh to continue stacking the deck for optimization. 1 single wash of laundry = 5kWh or 10% of the total of the entire energy budget for computing home automation for that year, conservatively.

So if you blame all the energy use of your HA budget on this one piston (that’s harsh) and you run a pi at 100% usage (you wont)… One wash would equal 10% of what it would be using for an entire year.

Yeah, min-maxing power subscription here this isn’t worth the effort, dude.

If you didn’t stack the deck… 10% usage of 50kWh of energy for HA compute power would be realistically 5kWh which is equal to our 5kWh for 1 wash. So the entire HA compute costs for the year would be easily used up by 1 wash. (still, being harsh on subscribing on power, since this is a single piston)

lol math.


Sorry, I should have elaborated a bit… (I was referring to more than just energy usage)


Every single piston that runs, needs power to the ST hub, power to the modem, and power to the devices connected. (the RPi was an unfair analogy)


Each and every execution must pass data from:
ST hub > modem > internet > modem > hub > device.

Frequency (external)

With a power trigger, this sequence of events happens potentially thousands of times a day.
(I have personally witnessed over a thousand an hour! So a thousand users with this single piston can create a million hits to the server per hour)

Frequency (local)

Add to this the fact that when our ST hub is spammed, then other pistons are more likely to “act up”.

Now, to clarify, I am not saying that you are doing anything wrong. I just am trying to emphasize how much non-stop activity you are creating with this logic.

I am curious, have you set Logging Level to Full for a bit yet to see behind-the-scenes?



If you share your other pics down below, I can insert them into your original post.


Yes, I’ve activated full logging on the dryer watch piston and it is idle between uses. The power monitor only sends out periodic kWh usage (once every… 4 hours or so) and only sends out wattage reports on change events… so the log isn’t like [0.0w…0.0w…0.0w…]

The log is busy during actual usage, but each power report takes an average of 160ms to complete the IF statement.

Event processed successfully (134ms)

Thanks, I think I was just given more privileges yesterday by the forum rule-set, so I just updated those.

I think the laundry reminder piston could still be better. I don’t really like the nested timers, but it seems to work when I tested it.


Consider yourself lucky. Most outlets are much more sensitive than this.

When idle, most will register 0.0w… 0.1w… 0.0w… 0.1w… 0.2w etc
(with each baby step registering as a change & triggering the piston)