Parts of Code as a Variable in rules

I have a question about if you can add parts of code into a string variable and reference it later in a rule.

Example:

I have a bunch of motion detectors that go off in the house and depending on the time of day, sun elevation and weather that makes the lights turn on and off.

For one of my weather items, I want to know if I can use parts of code instead of creating all of these lines for every different motion sensor, or if I want to edit it I have to do a lot of editing.

Here is the code I have.

if (TimeOfDay.state=="EVENING"  || (weather_forecasts0_condition.state=="Cloudy" || weather_forecasts0_condition.state=="Overcast" || weather_forecasts0_condition.state=="Mostly Cloudy")) {
		
			if (KitchenLightsS.state==OFF){
				KitchenLightsS.sendCommand(ON)
				Thread::sleep(1000)
				KitchenLights.sendCommand(75)
				logInfo("Motion.rules", "Turning on Kitchen Lights to 75%")
			}
		}

instead of doing this is every if statement…

(weather_forecasts0_condition.state=="Cloudy" || weather_forecasts0_condition.state=="Overcast" || weather_forecasts0_condition.state=="Mostly Cloudy")

How would you make something like the following work? I have tried with and without " " around the String

var String weather = (weather_forecasts0_condition.state=="Cloudy" || weather_forecasts0_condition.state=="Overcast")

To make this work?

if (TimeOfDay.state=="EVENING"  || (weather_forecasts0_condition.state=="Cloudy" ||  weather) {
		
			if (KitchenLightsS.state==OFF){
				KitchenLightsS.sendCommand(ON)
				Thread::sleep(1000)
				KitchenLights.sendCommand(75)
				logInfo("Motion.rules", "Turning on Kitchen Lights to 75%")
			}
		}

I have tried this without quotes and I get warnings in the code.


Cannot reference the field 'weather_forecasts0_condition' before it is defined

And then an error

Error during the execution of rule 'test': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.StringExtensions.operator_plus(java.lang.String,java.lang.String) on instance: null

Thanks for any help!

To create reusable code you could use Lambda’s (just search the community) or your mover your rules to use groups (again search the community)

For both you wil find some very good examples. Personally i prefer the group approach.

I’m not sure that is what im looking for.

All I want to do is take this piece of text…

(weather_forecasts0_condition.state=="Cloudy" || weather_forecasts0_condition.state=="Overcast" || weather_forecasts0_condition.state=="Mostly Cloudy")

… and populate it in multiple locations of different rules in the file. Then when if / if need to change it I don’t have to change 15 different rules with that line

Does that make sense?

I think there is no possibility to do so within openhab. Some day ago someone postetd something abot notification. He/She used ansible to create things dynamically. A key word is notification but i didt get it back in my mind

In the rules DSL, you would need to use a script (useable from other .rules files) or a lambda (only usable in the same .rules file). Using scripted automation, you can use a real scripting language, like Jython, and create a function that returns what you are looking for. This function can even be in a library that you can call from any of your other script files.

I think this is somewhat of an XY Problem. You’ve come up with the way you think you want to solve a problem and have asked about that which closes off other possible solutions that might work better. For example:

So why have lots of different motions sensor rules? Why not have just the one rule to handle all the motion sensors? That would solve the problem (don’t want to do a lot of editing, duplicated code) and in fact improve the situation as you will end up with even fewer lines of code over all.

How about Design Pattern: Separation of Behaviors? I see you are already using TimeOfDay which is a special case of Separation of Behaviors. Create a Rule that changes when TimeOfDay and weather_forecasts0_condition changes and set a flag (variable or another Item) that your various Rules check instead?

Or, as has been suggested already, Reusable Functions: A simple lambda example with copious notes. I don’t thin a Script would work in this case because you can’t get a return value from a Script.

NOTE: In OH 2 that long sleep is a really bad idea. You should schedule a Timer instead.

There are a whole host of ways to solve this problem. Many are documented in Design Pattern: DRY, How Not to Repeat Yourself in Rules DSL.

1 Like

I have different motion sensors rules for different motion sensors for bedrooms, bathrooms, hallways etc. that are different during different paramaters… I’m sure there is a way to do them now I kind of browsed through the posts about lambdas… but honestly, I’m not too smart with code, and it confused me a lot about what was going on.

I did not think of this. This is a great idea, and I think is the way that I will tackle this.

Thank you!

You might also want to use or implement something similar to…

This is very modular and additional actions can easily be added.