[SOLVED] Need help with rules on OH2

Hi folks.

Newbie to openhab.

I installed it 2x weeks ago, the latest running 2.4.0 and installed in Raspberry Pi3.
I’m using Paper UI and HABPanel.

I’ve been doing a lot of reading over the last 2x weeks and seeing contradictory information shared by users.
I see a lot of scripting references for Items, Rules, Cfg etc. and some users say that these are not required when using OH2 and MQTT2.4 since all config can be done via GUI.
I tried some examples as per many available on forums, but I always get an error in the OH log. They typically mention “no EOF” etc.

I’ve installed MQTT 2.4 and not familiar with any scripting.
After several days, I managed to get my Sonoff loaded with Tasmota to work to my OH2.
I have several Sonoff devices which includes BASIC, DUAL, RF Bridge and some PIR motion detectors.

I required to switch on a Sonoff BASIC when the PIR detects motion at night.
But it needs to switch off after several minutes, example 15min.
I don’t know how to achieve this via GUI.

So, the following is my setup…
I’m going to use a T1 light switch to control an outside light, but for this exercise to learn how to create this, I’ll be using a Sonoff BASIC.

The following is what my THINGS look like for the RF Bridge:
image
The detailed setup for above channel is:


What I’m achieving here is this: when the RF Bridge receives a 433MHz signal I extract the “data” portion as this is unique for any transmitter.
I then turn this received “data” into a command.
Here is an example of captured data when the PIR acts on motion and transmits to the RF Bridge:

Once above is received, I then run a rule. The rule then looks for a command to match and then performs on this action.
So, here is the rule:
image

The following is the actual TRIGGER:
image

The following is the action, if TRIGGER matches:
image

The following is currently the only condition, i.e. it will only work in the evening:
image

The GUI offers no method for timing.

This might offer an intro to GUI rules (aka NGRE)

As of 2.4, it doesn’t offer any useful timing features.

There are other methods to construct rules, you’l have seen examples of the text based xxx.rules files.

Hi Rossko.

Ok, thanks for the link. Spent some tonight on it tonight…
I’ve installed the JSR223 libs etc.
A lot of js scripts included, but can’t make head or tails from the contents.

I then tried the do the following:
From above original posting, I showed my single rule in place for the moment created via Paper UI.
I then updated the this rule to include an additional “then” function.
The first “then” triggers a Sonoff Basic to switch on, this is simulating my lights.
The second “then” is suppose to start a script.
The contents of this script contains a TIMER function which will then switch off the lights after some time.

See here the setup:


This shows the 2x “then” in UI.

image
This shows the setup inside the “then” to start the script.
I don’t know if this format is correct or path is correct.

This shows the actual contents of the script. This copied from some examples found.
image

But when I trigger the event, the light switches on…but the script event is not working and getting the following error on log:

Clearly a lot of things I don’t understand.

Looks like you found an example in the text files “DSL” syntax. The vast majority of examples will be. Don’t think that’s going to work by putting it in an xxx.py file where it expects python syntax.

Hi Rossko.

Sure. Before the xxx.py, I tried xxx.js but same issue.

So from online reading…I installed the JSR223 info…
I’m pretty sure that the scripting required must be presented in java format and the script file should be inside JSR223 folder.

Looking at the examples included, I guess the following is the closest to my needs for this topic:

/**
 * Copyright (c) 2018 by Helmut Lehmeyer.
 * 
 * @author Helmut Lehmeyer 
 */

'use strict';

load(Java.type("java.lang.System").getenv("OPENHAB_CONF")+'/automation/jsr223/jslib/JSRule.js');

var me = "TimerExample.js";
logInfo("################# "+me+" ##################");

JSRule({
	name: me+" TimerExample",
	description: "TimerExample L:"+__LINE__,
	triggers: [ 
		TimerTrigger("0/15 * * * * ?")
	],
	execute: function( module, input){ 
		logInfo("################ "+me+" Line: "+__LINE__+"  #################");
		
		logInfo( "createTimer start");
		createTimer(DateTime.now().plusSeconds(2), function(){
			logWarn( "createTimer stopped ");
		});
		
		logInfo( "setTimeout start");
		setTimeout(function(m){
			logWarn( "setTimeout stopped " + m);
		}, 1000, "bla");

	}
});

But from above, not clear what I can substitute for my own ITEM.

Dear folks.
Some catchup since previous post.

I’ve abandoned the rule concept via Java scripting and what else.
I don’t understand…
Having this said…I took a fresh approach to text file (so I will refer to this as plain scripting).
I mentioned in first post I tried this but always had a constant error showing up in Openhab log.
I went back to those errors and searched some on that and actually found numerous references to this…
So, the problem was with " - quotes…my text editor would use non-standard quotes and this would be a continuous problem…
So, now that I had that resolved I could move on and focus on other steps…
Which I managed well actually, considering spending many hours on them this past week with a lot of reading on posts etc.

Ok, let’s check my original intention with this particular rule required.
I want an outside light to switch on which is at my front door.
The light should only switch on when presence/movement is detected after hours.
It should stay on for a determined time.

Here is what I managed to get working successfully:

‘’’
//Rule to switch on outside left light after hours
var Timer MotionTimer = null

rule “Entrance left light timer”
when
Item GenericMQTTThing_RFBridgeRX received command EC65BE
then
logInfo(“Outside Left Light Timer Function”, “Outside passage motion detected!”)
GenericMQTTThing_UrnSwitch.sendCommand(ON)

  if(MotionTimer !== null) {
    MotionTimer.reschedule(now.plusSeconds(10))
  }
  else {
	    MotionTimer = createTimer(now.plusSeconds(10)) [ |
	    GenericMQTTThing_UrnSwitch.sendCommand(OFF)
	    MotionTimer = null
        logInfo("Outside Left Light", "Switched off!") 
	]
}end

‘’’
The ITEM triggers when a specific code is received.
It then logs INFO to openhab log, then switches on the light (I’m using a Sonoff Basic for testing).
After 10 seconds it switches off. In real life this will be changed to something like 15min.
If during the ON time, it triggers again, then the timer get updated (extended).
Once the light switches off, then again it logs the activity to openhab log.

So, very happy with this first setup.
I would like to add a “IF” to this to ensure this will only happen at night though…
But I’ll look at this later.

Now…i have another rule I built.
Similar to above…this rule will monitor my gate (gate to my driveway).
When the gate opens at night, it should again switch on some light.
In fact, I need this to switch on 2x lights.
I’m thinking of using GROUP to do this…but later though…
My first issue is the following:
The below script is working fine for testing where the gate opening is detected and the light switches on and after the timer runs out, the light switches off.
I then added a routine to check for hours…meaning I only want the lights to switch on if after hours.
When I added this…very little works…I don’t know how else to write the script.
I don’t understand how to place/write the IF…THEN inside another IF…THEN.

‘’’
//Rule to switch on both left and right front lights when the gate opens after hours
var Timer GateTimer = null

rule “Gate Light Timer”
when
Item GenericMQTTThing_RFBridgeRX received command AC2B99
then
logInfo(“Driveway gate”, “Gate moving!”)

if (now.getHourOfDay() >= 6 && now.getHourOfDay() < 23) { 
	GenericMQTTThing_WallFountain.sendCommand(ON)  [ |
	logInfo("All Front Outside Lights", "Switched on!")
	] 
}
	then
    	GateTimer = createTimer(now.plusSeconds(10)) [ |
		GenericMQTTThing_WallFountain.sendCommand(OFF)
		GateTimer = null
    	logInfo("Outside Light", "Switched off!") 
		] }
	else   {
}end

‘’’

Could someone guide me in above?

Okay, it may seem old fashioned in the face of fancy GUIs but there are more examples and it’s easier to share work, a good place to start out :smiley:

In this rules language, there is no if-then, or more precisely no then keyword in an if().
You didn’t use it in your rule that works.
then is strictly to divide rule trigger from rule body.

if (condition) {
    // do stuff
}

if (condition) {
    // do stuff
} else {
    // do other stuff
}

if (condition) {
   // do stuff
    if (other condition) {
        // do other stuff
    }
    // do more stuff
}

Indenting is not needed for it to work, it’s for you to keep your sanity working out which block belongs to which if

Hi Rich.

Thanks for above comments.
Did some more work and added the actual Sonoff light switches.

Below is my script when the gate is opening I have 2x sets of lights coming soon.
They have been added to a group and I control the group from this rule.
This works 100% for me.
This triggers only after hours, and the timer is a once of 15min cycle.
The rule currently still shows with a 10sec though for testing.

‘’’
//Rule to switch on both left and right front lights when the gate opens after hours
var Timer GateTimer = null

rule “Gate Light Timer”
when
Item GenericMQTTThing_RFBridgeRX received command AC2B99
then
logInfo(“Driveway gate”, “Gate moving!”)

if (now.getHourOfDay() >= 17 && now.getHourOfDay() < 23) { 
	Welcomelights.sendCommand(ON)
	logInfo("All Front Outside Lights", "Switched on!")
	GateTimer = createTimer(now.plusSeconds(10))   [ |
	Welcomelights.sendCommand(OFF)
	GateTimer = null
	logInfo("Outside Light", "Switched off!") 
	] }
end

‘’’

The next rule is when someone walks in the outside corridor leading up to the front door.
This rule has been updated with the actual Sonoff light switch.
It contains a timer and timer will also reset if PIR has been triggered multiple times causing the lights to stay on linger before switching off.

The only thing missing here…still don’t know how to add this…it to ensure this rule only works after hours.

‘’’
//Rule to switch on outside left light after hours
var Timer MotionTimer = null

rule “Entrance left light timer”
when
Item GenericMQTTThing_RFBridgeRX received command EC65BE
then
logInfo(“Outside Left Light”, “Outside passage motion detected!”)
GenericMQTTThing_LeftFrontOutsideLight.sendCommand(ON)

  if(MotionTimer !== null) {
    MotionTimer.reschedule(now.plusSeconds(10))
  }
  else {
	    MotionTimer = createTimer(now.plusSeconds(10)) [ |
	    GenericMQTTThing_LeftFrontOutsideLight.sendCommand(OFF)
	    MotionTimer = null
        logInfo("Outside Left Light", "Switched off!") 
	]
}end

‘’’

Is there a reason you haven’t tried wrapping the whole rule body in an

when
    // trigger
then
   if (hours condition) {
       // existing rules stuff
   }
end

exactly like you already did for the gate rule?

Hi Rich.

Yes I did try this…however…the problem then is the timer reset, or timer reschedule.
I don’t know how to reset/reschedule the timer if timer already running and another motion is detected in the meantime so that the timer value can be extended.

You’re already doing that in the rule you showed us. On motion, it reschedules if the timer is already running, or creates a new timer if not.
If its not in-hours, you need do nothing.

Hi folks.

Allow me to give some feedback on above.
Been at this for 3x weeks…or…actually more like 2x weeks…I’ve been away for 1x week vacation in the bushes.

I’ve done quite a bit…or rather learned quite a bit more on the systems…
Let me show you what I achieved.

there are some more things I need done…but I think best I address those under new topics.

So…one of my first problems was to create a timer triggered by a PIR and this should only happen after hours.
Then, I had to try establish when exactly is after hours, meaning night time.

So this is how I got them resolved.

First…I created a rule to indicate when it is night time and day time:

//Rule to know when night starts and stops

rule "Sunset Rule"
when
    Channel 'astro:sun:local:set#event' triggered END
then
    NightTime.sendCommand(ON)
    logInfo("Night status", "Now turned NIGHT time!")
end

rule "Sunrise Rule"
when
    Channel 'astro:sun:local:rise#event' triggered END
then
    NightTime.sendCommand(OFF)
    logInfo("Night status", "Now turned DAY time!")
end

This works great for me. So, what I did was to create a SWITCH in ITEMS “NightTime”.

Now, I created a new rule and this switches on an outside light covering my porch entrance.

//Rule to switch on outside left light after hours
var Timer MotionTimer = null

rule "Entrance left light timer"
when
    Item GenericMQTTThing_RFBridgeRX received command EC65BE
then
    logInfo("Outside Left Light", "Outside passage motion detected!")

	if (NightTime.state == ON) { 
		GenericMQTTThing_LeftFrontOutsideLight.sendCommand(ON)
		logInfo("Outside Left Light", "Switched on!")
		MotionTimer = createTimer(now.plusMinutes(10)) [ |
		GenericMQTTThing_LeftFrontOutsideLight.sendCommand(OFF)
		MotionTimer = null
	logInfo("Outside Left Light", "Switched off!") 
    	] }
	end

From above, rule only active if the “NightTime” status is “ON”.

I created another rule, this time when the outside driveway gate opens.
Again I have some lights switch on…the same as per above, the porch light…but also a second light covering the parking area in front of the garage.
Take note here…I used a GROUP as the function. So I added 2x lights into the same GROUP.

//Rule to switch on both left and right front lights when the gate opens after hours
var Timer GateTimer = null

rule "Gate Light Timer"
when
    Item GenericMQTTThing_RFBridgeRX received command AC2B99
then
	logInfo("Driveway gate", "Gate moving!")

	if (NightTime.state == ON) { 
		Welcomelights.sendCommand(ON)
		logInfo("All Front Outside Lights", "Switched on!")
    	GateTimer = createTimer(now.plusSeconds(10))   [ |
   		Welcomelights.sendCommand(OFF)
   		GateTimer = null
    	logInfo("Outside Light", "Switched off!") 
    	] }
	end

Above rule is triggered after hours via a RF transmitter with a magnetic strip.

Very happy with above…and to most of you this must seem like simple mundane stuff…but this is huge for me.

Then I got onto my next project…timing…I needed certain function to happen at certain times of the day.

Here is my next project.
A little detail around the hardware…I’m using SONOFF light switches and relay and the are all loaded with TASMOTA.
The following is a rule to control 2x fountains I have in the garden.
Or, rather, I have a small fountain in the front garden, then another larger fountain next to our front entrance.

//Rule to switch on front small fountain

var Timer smalltimer = null
var Timer walltimer = null

rule "Small fountain operations"
when
    Time cron "0 5 12 ? * * *" // runs everyday at 12:05
    or
    Time cron "0 5 7 ? * * *" // runs everyday at 07:05
    or
    Time cron "0 5 16 ? * * *" // runs everday at 16:05
    then
        GenericMQTTThing_SmallFountain.sendCommand(ON)
        logInfo("Front fountains", "Small fountain switched on!") 
        smalltimer = createTimer(now.plusMinutes(70))   [ |
   		GenericMQTTThing_SmallFountain.sendCommand(OFF)
   		smalltimer = null
        logInfo("Front fountains", "Small fountain switched off!")  ]
end

//--------------------------------------

//Rule to switch on wall fountain in the mornings and midday

rule "Wall fountain morning and midday operations"
when
    Time cron "0 0 13 ? * * *" // runs everyday at 13:00
    or
    Time cron "0 0 9 ? * * *" // runs everyday at 09:00
    then 
        if (VacationSW.state == OFF)
            GenericMQTTThing_WallFountain.sendCommand(ON)
            logInfo("Front fountains", "Wall fountain switched on normal times!")  
            walltimer = createTimer(now.plusMinutes(60))   [ |
            GenericMQTTThing_WallFountain.sendCommand(OFF)
            walltimer = null
            logInfo("Front fountains", "Wall fountain switched off!")  ]
end

//--------------------------------------

//Rule to switch on wall fountain in the afternoons

rule "Wall fountain afternoon operations"
when
    Channel 'astro:sun:local:civilDusk#event' triggered START
    then 
        if (VacationSW.state == OFF)
            GenericMQTTThing_WallFountain.sendCommand(ON)
            logInfo("Front fountains", "Wall fountain switched on before sunset!")  
            walltimer = createTimer(now.plusMinutes(60))   [ |
            GenericMQTTThing_WallFountain.sendCommand(OFF)
            walltimer = null
            logInfo("Front fountains", "Wall fountain switched off!")  ]
end

The first 2x portions of above rule I found easy to have implemented.
First portion is to run the small fountain in 3x cycles during the day.

The second portion is the larger wall fountain and that causes it to cycle twice every day.

But, the final portion was the most difficult…this took me days to solve, again with many hours of reading and experimenting.
What I was trying to achieve and finally got working…
The wall fountain runs 3x cycles per day.
First cycle early in the morning. The second cycle around lunchtime.
The final cycle is late afternoon. But, the issue I had…which is exactly right now…is the season.
So, being in WINTER at the moment…if I use CRON, then I could simply put a starting time down and voila…working. But, when summer comes…it will be running too soon…and I would have had to adjust the CRON time again.
The solution I was looking for was to use SUNSET time.
Use some sort of method to detect SUNSET but then start the wall fountain and run it for 1x hour and make it stop at SUNSET time.

I eventually got this sorted once I learned of the “OFFSET” function.
From the script you would see that I used “CIVILDUSK” event to detect the SUNSET period and I implemented via PAPER-UI a “-60” offset.

ok, so few more small things I’ve done but I think this is enough feedback here for now.

I now have a new quest regarding automation for pools…but I will start a new topic for this.

By the way, Rich and Rosko…I think I go the hang now of using THEN and IF…ELSE commands.

2 Likes