I don't know how to do it - wait for a certain value then execute action

Hi folks,

I have an audio-player, and I want it to stop, when song ends, not in the middle of the song.
I want to create a rule, which checks the item state (track_duration), and if the state reaches a certain value (0), execute actions on other items (send stop to player,switch smartplug off).

In other words:
-> if stop signal detected -> detect track_duration and wait for “0” -> stop player -> switch smartplug off

But I don’t know the syntax or even the action to use… I was thinking about “while” but can’t figure out how to do it - anyone??

My main problem is I don’t know how to tell openhab to wait for the value.

Any suggestions appreciated!

thanks folks,

Dan

How about a rule that triggers when track_duration == 0?

@rule("Speaker stopped")
@when("Item track_duration changed to 0")
def speaker_stopped(event):
    events.sendCommand("Smart_Plug", "OFF")

The art is, you don’t try to do that.

You can tell it to look every time the value changes. There’s no need to wait.

You can refine that, into “every time the value changes to something specific”, like Scott’s example.

1 Like

hi guys :wink: thanks for your suggestions…

I think I have to explain this alittle more to you, because I don’t have the ability to do it like this…
I have a rule, that fires up lights and music to a room with a 45mins timer.
When the timer has expired, the music shouldn’t stop immediately but when the actual track is over.

rule "Gym Time Launch"
when
	Item GymTime received command ON
then
	if ( GymTime.state = ON ) {
		logInfo("Actions", "Gym-Time started already, doing nothing ")
		return;
	}
	
	gymTimer?.cancel
	Smartplug01Switch.sendCommand("ON")
	SqueezeGymPlayFavorite.sendCommand("21")
	if ( RGBBulb03Switch.state != ON ) {
        RGBBulb03Switch.sendCommand("ON")
    }
	gymTimer = createTimer(now.plusMinutes(45)) [ |
--------->> this is where the magic should happen <<-----------
		RGBBulb03Switch.sendCommand("OFF")
		SqueezeGymPower.sendCommand("OFF")
---------------------------------------------------------------
		GymTime.sendCommand("OFF")
		gymTimer = null
		Smartplug01Switch.sendCommand("OFF")
	]
end

rule "Gym Time Cancel"
when
	Item GymTime received command OFF
then
------------------->> and here ;) <<------------------------
	SqueezeGymPower.sendCommand("OFF")
	Smartplug01Switch.sendCommand("OFF")
------------------------------------------------------------
	gymTimer = null
end

I hope I don’t confuse you too much with that, sorry…

Dan

Yes you do. Everytime the track duration changes to 0, you look to see if the 45 min timer has expired. If it has, do this, if it hasn’t, do that.

hmm but I couldn’t barely imagine how to do this in my rule?!??
sorry could you explain a little further what you think please…

Dan

You’d would need your 45 minute timer to be referenced by a global variable, so that any other rule in the same rule file can “see” it.
Looks like you already do that - gymTimer ?
This variable is null when the timer is not running.

Now make a rule that runs every time the track duration changes to 0
This rule then looks to see if the timer is null.
If it is, the timer has finished and you do whatever.
If it is not null, the timer is still running and presumably you do nothing.

ahh ok I see… but the duration can not be the trigger of the rule I think, because if there’s music in this room not fired by this specific timer, it would stop after every track and I have to avoid this…

Thanks for your effort
Any further suggestions maybe?

Dan

You get what you ask for, so be sure to give the whole story, it will save you time.

So, to have the rule take effect only when the timer has expired, and not to interfere unless the timer has been used.

Alter your timer so that it does NOT set its own handle to null at execution time.

Alter the rule that runs every time duration changes to 0
Instead of timer===null , look for timer.hasTerminated as the prerequisite for “doing whatever”
Add a line to the whatever to set the time handle to null, now that it is finished with.

In real life you’ll get into this rule and test when the timer handle is null, but you cannot test the hasTerminated property of null, it hasn’t got one.
The actual test you’d need -
if (myTimer !== null && myTimer.hasTerminated) {
will avoid errors, it will bail out early when null.

you’re right… but english is not my native language and it was a little hard for me to explain this situation completely :wink:

Sorry for that - I’ll try your suggestion…

thanks again

edit:
I’ve seen you updated your post thanks for further explaining this