Master manual switch

Hi all.
Me and my wife has come to the agreement that what our home automation needs a master switch that puts it into “manual mode”, ie when this switch is on most of my rules shouldn’t be run. So that when we have people over for dinner the house don’t suddenly get all dark at eleven just because that’s what we normally want. I’m looking for some input on what would be the easiest way to implement this.

The obvious way would be to put extra if clauses all over my rules, checking this master switch before anything is done. Problem is that this would clutter up all rules with this extra logic. So I’m wondering if there is some more elegant solution I’m not seeing. Like some way of simply saying that rule this and that should simply be temporarily inactivated. Ideas?

This would be sooo easy with the Experimental Rules Engine and I think you will want to consider moving over to it in the near future as it matures. Unlike with the old rules which only have a “when” clause full of triggers, it also has a section that checks the state of Items before the rule triggers.

But in the old rules engine, this is a lot tougher. I’ve come up with a couple of alternative approaches but they all fail on some level or other to make this more elegant or you lose some capability in your rules.

For example, you could centralize your if statement into a lambda and pass the body of your rule to this as a lambda. It would look something like this:

import org.eclipse.xtext.xbase.lib.Functions

val Functions$Function1<Functions$Function0,Boolean> masterSwitchTest = [ Functions$Function0 lambda |
	if(MasterSwitch.state == ON) {
		lambda.apply()
	}
	true
]

rule "Some rule"
when
    // some trigger
then
    masterSwitchTest.apply([|
        // body of your rule
    ])
end

But is that really any better than just using an If statement there in the first place? It could be useful if you had more interesting things you want to do to decide to run a rule, but for just testing one Switch I’d say it is not worth the effort.

There was another thread saying that the return statement does not behave as expected (i.e. doesn’t always exit the rule) so I don’t think you can get away with a simple:

if(MasterSwitch.state == OFF) return

or

if(MasterSwitch.state == OFF) return false

This second one will give you errors in the logs but it should work functionally.

You could try

if(MasterSwitch.state == OFF) break

though I’ve not tried break myself in a long time and I don’t remember how well it works.

One idea could be to use executeCommandLine to move the .rules file somewhere else when MasterSwitch turns ON and move them back when MasterSwitch turns OFF. You will have to be sure to preserve the one file where these moves take place though. This might be the more elegant of the ideas I’ve thought up so far.

2 Likes

Thanks a lot for all the suggestions! Seems at least there are a few decent ways to do this even though none of them are really perfect.

About the new rules engine, I last tried it out somewhere around the release of 2.0 and I gave it up pretty soon, it couldn’t do half of the things I wanted. Guess it may be time taking a look at it again…

Hey guys,

I have to slightly disagree. Rules are there to define how your system is supposed to react in the case of an event. NOT to do something depending on certain conditions is just as much an important part of the rule as any other. I also found, that only a few rules need to be disabled for the manual switch (I also have one).

@rlkoshak your lambda solution is odly complicated. Why not a simple if?

Here’s how I’m going at it:

rule "Some rule"
when
    // some trigger
then
    if (masterSwitch.state == ON) return false
    
    // body of your rule 
end

Here is the thread regarding return:

1 Like

Because op was specifically looking for a way to do it without having to put an if statement in every rule. I mainly listed it to illustrate that there really isn’t a simpler way than using the if statements, though the idea of moving or renaming the rules files doesn’t feel too bad to me.

I think the hesitation about using the if statements is because it really feels like a violation of Don’t Repeat Yourself.

And you will see I suggested the same return false approach in my reply after providing examples to prove there really isn’t a simpler way.

1 Like

I didn’t want to provoke you. :slight_smile: I also saw your alternatives. Just wanted to post my working and tested solution (btw. break is not supported, at least not in 2.1 stable).

Best!

Thank you both for great input! I think this one feels like the best one.

You are most certain right in that many of my rules are not affected by this, I need to go through them and sort them out.

Not provoked, just a bit grumpy these days. I don’t want to come off as such but sometimes it is hard to avoid.

I need to run some experiments about break sometime. Most of the time I’ve tried to use break and return has been from inside a lambda and I found that if I use either inside a lambda it would exit the whole rule, not just the lambda. But that was many versions ago.

That’s working perfectly fine now. See: openhab-config/rules/heizung-raeume.rules at a53ddeb0727c67ee1f42cce5efc01d82f6684a75 · ThomDietrich/openhab-config · GitHub

1 Like

Ok, I get the “Void functions cannot return a value.” Am I understanding the linked thread correctly that this error is safe to ignore and everything will work? I’m running 2.1.

I had another look and it turns out, that the issue was tackled and will be solved in newest snapshot and later stable release versions. If I understand the change correctly this is the solution you should go with:

if (masterSwitch.state == ON) return

This one will still yield the “Void functions cannot return a value” with 2.1 stable but will already do what it is supposed to.

1 Like