Help with Rules please

I have some switches that toggle my projector and projector screen on and off at the same time. I want to get a little fancier and create a rule that checks if the TV is on, and if it is, it should turn it off THEN turn on the projector and the screen, and if it is already off THEN simply turn both the projector and the screen on. The issue I’m having is that i can’t get the switch to turn the projector and the screen off after i’m done using them. I think the problem lies within the rule itself, i don’t know how to structure it to toggle them off. See below for my current rule

rule "Projector-Movie"
    when
        Item samsung_tv_state_projector_movie received command
    then
        if(receivedCommand == OFF) {
            sendCommand(Samsung_TV, ON)
			Thread::sleep(10)
			sendCommand(Movie_Mode_On, ON)
            
		}
		else if (receivedCommand == ON) {
            sendCommand(Movie_Mode_On, ON)
		}
		else {
			sendCommand(Movie_Mode_Off, ON)
		}
end

Is there something that can be added to the rule that counts and checks if this command “sendCommand(Movie_Mode_On, ON)” has been sent and if it has it will then send this command “sendCommand(Movie_Mode_Off, ON)”?

EDIT: i should add that i dont have a way to check the state of either the projector or the screen.

if(Samsung_TV.state == ON) Samsung_TV.sendCommand(OFF)

Good evening Rich,

Where should i place this in the rule?

EDIT: The rule works as intended from beginning through this part:

rule "Projector-Movie"
    when
        Item samsung_tv_state_projector_movie received command
    then
        if(receivedCommand == OFF) {
            sendCommand(Samsung_TV, ON)
			Thread::sleep(10)
			sendCommand(Movie_Mode_On, ON)
            
		}
		else if (receivedCommand == ON) {
            sendCommand(Movie_Mode_On, ON)

How can it turn both projector and screens back off?

I have three items i can use:

  • Movie_Mode_On, which is a macro that turns things ON regardless of the command you give it
  • Movie_Mode_Off, which is another macro that turns things OFF regardless of the command you give it
  • Movie_Mode, which is a switch with the ability to turn things OFF and ON (basically the above two combined, one for ON, and the other one for OFF

I’m sorry if this comes across as unhelpful, but what you are asking is the most basic of basic rules logic. If you are struggling with this you will have a long and hard time of it.

If you haven’t already, read and re-read the Rules section of the docs. You might consider going through an online beginner’s programming course.

Also go through the Beginner’s Tutorial.

Here are all the parts you need to know:

  • to turn OFF a Switch you use MySwitch.sendCommand(OFF)
  • to turn ON a Switch you use MySwich.sendCommand(ON)
  • to check if a Switch is on use if(MySwitch.state == ON)
  • to check if a Switch is off use if(MySwitch.state == OFF)

So, to turn your Movie_Mode to off you use the second bullet from above.

No apologies needed Rich. I’m the one to apologize for not stating my problem correctly. I appreciate your efforts despite my stupid questions. See below.

Items:

Thing:

  • network:device:samsung_tv [ hostname=“192.168.1.23”, refresh_interval=“10000” ]

Rule:

rule "Projector-Movie"
    when
        Item samsung_tv_state_projector_movie received command
    then
        if(samsung_tv_state_projector_movie.state == OFF) {    // _If TV is On_ 
		
			Samsung_TV.sendCommand(OFF)  //_Turn it off_
            Thread::sleep(10)                                          //_Wait_
			sendCommand(Movie_Mode, ON)   //_Turn on projector and screen_
            
		}
		else if (samsung_tv_state_projector_movie.state == ON) {        // _Else If TV off, no need to do anything to TV so..._
            sendCommand(Movie_Mode, ON)              // _....Turn projector and screen on_
		}
		else if (Movie_Mode.state == OFF) {        //_This part is where i have an issue, how do turn projector and screen off? You said to check the state of the switch, but all it does is to send the ON command again to the projector and the screen_
		    Movie_Mode.sendCommand(OFF)
		}
end

All I’m looking for is for the TV to be OFF or be turned OFF before the projector is turned on and the screen comes down, and then turn the projector and the screen off when i’m done.

I understand what you are trying to do. As written your Rule makes absolutely no sense whatsoever and shows a very drastic lack of understanding of the basics of OH.

You have the rule being triggered when the TV goes on or off the network. Don’t you want the Rule to trigger when you press a button on the sitemap to say “I want to watch the projector?”

Once in the rule the logic is super simple:

if(receivedCommand == ON) { // i.e. you pressed the button to turn on the projector and lower the screen
    if( samsung_tv_state_projector_movie.state == ON) Samsung_TV.sendCommand(OFF) // turn off the TV if it is ON
    Movie_Mode.sendCommand(ON) // presumably turn on the projector and lower the screen?
}
else { // i.e. you pressed the button to turn off the projector and raise the screen
    Movie_Mode.sendCommand(OFF) // presumable turn off the projector and raise the screen?
}

I figured out Rich. I’m sure i tested your patience so thanks again for all you do. As i read your examples, examples on other posts and “reverse engineer” them i’m starting to understand a bit more each time.

Here is the final rule; i hope i made you proud lol:

rule "rule triggered by Movie_Mode1"
    when
        Item Movie_Mode1 received command
    then
        if(receivedCommand == ON) { 
    if( samsung_tv_state_projector_movie.state == ON) Samsung_TV.sendCommand(ON) 
    Movie_Mode_On.sendCommand(ON)
	Movie_Lights.sendCommand(OFF)
}
else { 
    Movie_Mode_Off.sendCommand(ON)
	Movie_Lights.sendCommand(ON)
}
		
end

That makes me happy. :grin:

I wasn’t getting frustrated. I’ve just been burned in the past when I’ve simply have the code away before in these sorts of postings. One of them turned into me spending 40 hours of my own time implementing a very complicated set of rules and the person simply refused to try to learn how to learn to take it to the next level.

I finally gave up and now I take the “teach a man to fish instead of give a man a fish” approach. If some shows a willingness to try and learn themselves I’m much more willing to do the code myself for them because I know they will learn from it. Or if they have a particularly interesting problem I’ll solve it for them. That is where most of my best design patterns came from.

Indeed! And I’ll be a lot less circumspect with you in the future. With a handle like illegalzinc I’ll remember you when you post in the future.

2 Likes

Thank you again Rich.

Quick question, as I continue to get “fancier” with my set up, on the example above, after “else {” can you "call’ another rule? Like:

else {
" call xxxxxx.rules"

So it checks another rule that has other conditions before it sends any other commands?

AFAIK, you can not call rules, they are triggered by events.
You can call functions, that are written in the same file as your rule/s. Take a look at Rich’s examples:

Thanks George! As soon as I posted my last message I went and googled “rules within rules in opehab” and found the Labmda threads. If I was having big issues with basic rules I can only imagine what I’d go through if I try calling functions :sweat_smile:. I mean, for simple on and off switches that I control now, I think that rules will do :laughing:

How about this, how many “else if” can I have in a rule to check the state of other stuff?

Why don’t you use?:

switch {
case // some code
case // some code
// and so on
}

Using my rule above, can you elaborate a bit George?

As Rich was saying, please try and do something! You are getting better if you are trying! Of course I can solve your “homework”, but that will not teach you to “fish”!
Cheers!

True that. I guess what I was hoping for was a real life example, and I could make that work for anything else I need. Thanks!

1 Like

Besides lambdas, there is the Separation of Behaviors DP.

But you really only want to use either option if you need to execute the same code from multiple rules.

Finally, you can have as many else if statements as you want. Switch is a good alternative but not as common in the examples.

A normal usage would be something like:

switch(someString){
    case "Foo": {
        // Do stuff when someString == Foo
    }
    case "bar": {
        // Do bar stuff
    }
    default: {
        // Do stuff when no offer other case matches
    }
}

You can have as many cases as you want. The Rules DSL, unlike most other languages, let’s you put arbitrary conditionals in the case. So you can have a case like:

case some value == ”Foo" && otherValue.length > 3: {
    // Do stuff
}
1 Like

Thanks again!