Washing Machine State Machine

I went with the Aeotec Smart Switch 6. It took a little bit of work to get it to report values, but that may mainly have been user error. Has anyone tried Aeotec’s heavy duty smart switch? I’d like to use that to monitor my dryer (which needs 220V). Monitoring the dryer is a little more important because it’s cycle generally takes longer than the washer.

I’ve had good luck with my NodeMCU based vibration sensor for dryer detection.
You’re welcome to check it out and use it if you would like https://github.com/cbfief/laundrySensor.

It includes code for a photoresistor based washer sensor also (not working so well), but you should be able to strip that out fairly easily despite the current lack of documentation.

I used a SW-420 vibration sensor, but any similar sensor should work just fine with some tuning.

An alternative that I use to find out when my washer has started and ended is an old mobile phone charger powered from the door lock contacts. The charger then operates the coil of a relay which is a GPIO contact item on my Pi.
Mine is an older machine and as I use it on the same cycle it always takes around the same time so I can also predict when it will end.
Rather obviously don’t go in there without turning the power off first and don’t do this if you don’t know how to keep things safe in a high vibration, environment

I’m having a problem myself, if others can confirm this I’ll need to file an issue. Especially hoping for feedback by @rlkoshak :wink:

Check out the example in the first posting. At the end, you will find this rule as an example for further actions:

rule "Washingmachine Notifications"
when
    Item Washingmachine_OpState changed
then
    if (Washingmachine_OpState.state == MODE_FINISHED) {
        pushover("Washingmachine finished!")
    }
end

I wanted to straighten the logic. This does not work (no error or exception):

rule "Washingmachine Notifications"
when
    Item Washingmachine_OpState changed to MODE_FINISHED
then
    pushover("Washingmachine finished!")
end

This is working as expected:

rule "Washingmachine Notifications"
when
    Item Washingmachine_OpState changed to 3
then
    pushover("Washingmachine finished!")
end

Can anyone confirm that 1. using variables in the event definition is not working and 2. it should?

I’ve never actually seen an example of using a variable in the trigger like that. I’ve only ever seen or used hard coded constants (i.e. your 2nd example).

Do we know if using vals in triggers has ever been supported?

I know for sure Numbers like in your second example work, as do ON/OFF, OPEN/CLOSED, etc. states. There are other threads where people notice that Strings do not work (again, I’m not sure if that was ever supported, though if Numbers are supported is seems Strings should be).

I think it is absolutely worth filing an issue for it (ESH is probably the right place). I just don’t know if that issue would be an enhancement or a regression.

I think it’s important to mention, that I’m working with a constant (val) here. This would be a completely different question, if I was trying to compare to a variable that could change over time.

How do you build your state machines then?

Thought so too, just wanted to clarify that I’m not missing a detail or an error in my logic.

I trigger the rules on update or change or received command or whatever is appropriate. Then I check the state inside the rule in if or switch statements.

My rules may get triggered more than they should but performance has never been an issue.

Why do you use variables for the state of the washing machine?

Couln´t you do that with numbers only?

Is it only so you can better read the rule or is there another thing, why you do this?

This. :wink:
However I wouldn’t underestimate the importance of that. The 1-year-future me will be thankful :smiley:

2 Likes

Future me really hates past me’s code too! :slight_smile:

I actually use Strings to define states like this instead of numbers as I find them a little more self documenting.

1 Like

Past me tells me to avoid wasting memory :laughing: That would actually make a few things cleaner but with that not even my second solution would work…

Meh, memory is cheap. It is more expensive for CPU as well. But I’ve learned over the years that is it more important to make code that executes infrequently (once per minute or less frequently) short, concise, and easy to understand than it is to make it fast and efficient.

Indeed your second approach would not work any better with String, but you would be able to eliminate your MODE_FINIDHED val entirely and use:

Item Washingmachine_OpState change to "FINISHED"

Of course, this assumes that support for Strings in Triggers is supported and not currently broken.

If you already have such a state machine, could you test that?

Sorry, for hijacking the thread, but talking about flexible triggers: I’m thinking of condition in triggers. e.g. I’d like to have a frost warning, if the temperature sinks below -2°C. At present, my rule is:

rule "Frostprüfung"
when
	Item Sensoren_Temp_OutN received update
then
	if (Sensoren_Temp_OutN.state < -2 && Binder_Frost.state == OFF) {
		sendCommand(Binder_Frost, ON)
	}
	if (Sensoren_Temp_OutN.state > -2 && Binder_Frost.state == ON) {
		sendCommand(Binder_Frost, OFF)
	}
end

I don’t know about load, but if it would be possible to use something like.

rule "Frostprüfung"
when
	Item Sensoren_Temp_OutN changed to "< -2"
then
	if (Sensoren_Temp_OutN.state < -2 && Binder_Frost.state == OFF) {
		sendCommand(Binder_Frost, ON)
	}
	if (Sensoren_Temp_OutN.state > -2 && Binder_Frost.state == ON) {
		sendCommand(Binder_Frost, OFF)
	}
end

but, if such complex triggers would blow up the logic and the if-clauses are faster already, I’m fine.

I believe the system should stay with simple state comparison here and higher logic can be done inside the the rule as you showed. However “simple state comparison” should work up to a certain degree and I/we believe that comparison with a (constant) string and a (constant) val should be supported because of that reason. @rlkoshak I’ll create a ticket for both after you’ve tested String comparison.

1 Like

Unfortunately my only state machine at the moment is my Time of Day stuff. I’ll set up a quick test and see if it works in the morning.

These sorts of triggers were never supported and probably never will be in the current Rules DSL. But I think they will be supported in the Experimental Rules DSL.

Ran the test last night. My test rules did not trigger. Changed to “string” does no appear to work right now. I’m running a build that is only a couple of days old.

Hi,

I’m new to openhab so please bear with me. I was wondering if anyone could give me some idea of how to handle the state machine for my dryer. I’ve included a picture of the power usage and as you can see it has two quite long time period during the active phase were the consumption goes down but the main problem however is at the end. My machine has a feature to prevent wrinkled laundary so once it is finished it starts to rotate every minute or so. That is what you can see at the end. It does this for an hour but during that time I can empty it as I please.
My though was to set my IDLE to ACTIVE if statement quite high (say >350) but then I have the power drops in the middle in the active phase that are quite long (around 5 mins).

Could anyone give me a hint on how to use a timer based approach to handle this gap?
It’s been a while since I did any programming.

var Timer timer = null

rule "Dryer state machine"
when
    Item Dryer received update
then
    if(Dryer.state > 350) {
        if(DryerState.state != "ACTIVE") DryerState.sendCommand("ACTIVE")
        if(timer == null) {
            timer = createTimer(now.plusSeconds(330), [|
                DryerState.sendCommand("IDLE")
            ]
        }
    }
end

Five minutes and thirty seconds after the dryer’s power drops below 350 the state will go back to IDLE.

If you want it to go to “IDLE” immediately after it is done, during that dewrinkle period, you will have to keep track of each of the five power usage cycles and go to idle after you reach the last one.