Rule not updating

Hi all.
I wrote the following rule, which I think was kinda clever:

rule "Z-Wave tempsensor updated"
when
Item ZWaveMultiSensor_SensorTemperature received update
then
if(timer_z!=null) { timer_z.cancel }

    if(TellstickTemperature1_ActualTemperature.state==NULL ||
            ZWaveMultiSensor_SensorTemperature.state < TellstickTemperature1_ActualTemperature.state) {
            postUpdate(Utetemperatur, ZWaveMultiSensor_SensorTemperature.state)
    }
    timer_z = createTimer(now.plusMinutes(5)) [|
            postUpdate(ZWaveMultiSensor_SensorTemperature, NULL)
            sendMail("removed", "Fel på tempsensor", "Har inte fått något värde ifrån sensorn på uteplatsen på 5 minuter.")
    ]

end

It’s supposed to:

A. Make sure the sensor doesn’t show any old values, if I haven’t got any value for a while it’s set to null instead.
B. Update a “virtual” sensor (ie an item not connected to any channel) called “Utetemperatur” so that it always shows the lowest value of this sensor and another, so that if either sensor is broken or if the sun suddenly shines on either of them, I have a sensor with a good value anyway. (I obviously have a similar rule for the other sensor involved)

Sadly I realized that this became a race condition. This Z-Wave sensor sends values every fifth minute, half of these times the timer set of before the value was sent. So when I woke up the following morning my mailbox was kinda full with errors.

The strange thing is that I raised the value of the timer. First to ten, then 30 and then 60 minutes and got the same amount of mails. When saving the log I get the “Refreshing model” in openhab.log, so it’s clearly reading my new rules file, but anyway I get this in the events.log:

2017-02-12 18:31:47.981 [ItemStateChangedEvent ] - ZWaveMultiSensor_SensorTemperature changed from 0.1 to 0.2
2017-02-12 18:36:47.462 [ItemStateChangedEvent ] - ZWaveMultiSensor_SensorTemperature changed from 0.2 to NULL
2017-02-12 18:36:47.807 [ItemStateChangedEvent ] - ZWaveMultiSensor_SensorTemperature changed from NULL to 0.1
2017-02-12 18:46:47.773 [ItemStateChangedEvent ] - ZWaveMultiSensor_SensorTemperature changed from 0.1 to 0
2017-02-12 18:56:47.575 [ItemStateChangedEvent ] - ZWaveMultiSensor_SensorTemperature changed from 0 to NULL

So it’s clearly still setting the value to null after five minutes, even though the timer in my rules file now says 60 minutes. Any ideas why this would happen. I tried restarting entire openhab, didn’t help.

edit: Also if anyone could tell me what I’m doing wrong when pasting my code I’d be grateful. Looks like crap the way I did it now, doesn’t it?

When you reload a rules file, it does not kill any timers already spawned - so you can see lingering effects for a while.

Which does not i think explain most of what you see. If you suspect “ghost” rules, put a tell-tale in your ‘current’ timer version to distinguish it from any previous version - logInfo(“testing”,“new edit”) or something.

Have you defined timer_z globally? So that it can be cancelled - else you’ll spawn new timers every time

Have you seen Expire binding, as an alternative approach?

1 Like

Thanks for your response!

This is a z-wave-device that was created using smarthome inbox. I’d love to use Expire but if I’m correct that’s only possible when creating devices using files, right?

Don’t know if it will make a difference, but try canceling the timer with:
> if(timer_z!=null) {
> timer_z.cancel
> timer_z = null
> }

[quote=“DanielMalmgren, post:3, topic:22815”]
When you reload a rules file, it does not kill any timers already spawned - so you can see lingering effects for a while.

Any idea how much “a while” is? I’m now on the third day and counting.[/quote]
Purely the maximum period of any timers you may have made. I just pointed this out, because I’ve seen more than one thread where is gnashing of teeth when an error is generated shortly after rules reload, when it shouldn’t really be of much concern as is distracting from the real problem.

So far as I know the Expire binding is currently a 1.x binding, but works under OH2. So long as you can add it to an Item somehow, I don’t think editing methods come into it.

[quote=“DanielMalmgren, post:3, topic:22815”]
Well, for every time that I’ve raised the timer timeout I’ve also changed the text in the mail that’s being sent and the mail I get contains the “new” text…[/quote]
Okay, so what did that reveal? Your first post was bit ambiguous suggesting the timer was sending eMails every 5 mins even if the period was 30 mins?

Alpoy’s suggestion to null the timer, as well as cancel, is certainly the conventional way to do it.

Thinks; you said there was a “sister” rule - not using the same timer is it?

Yep, after some more hours fiddling around with these rules I’m starting to understand what you mean. Every time one changes even the slightest little thing the best thing is to wait for all old timers to expire before drawing any conclusions about the effect…

I still don’t understand where I’d put the expire rules in items that I’ve configured only through the GUI (paper UI/Habmin).

Anyways, I’ve now made rules that actually do exactly what I want, they look like this (I’ll paste the entire file this time):

import org.openhab.model.script.actions.Timer
import org.joda.time.*

var Timer timer_t
var Timer timer_z

rule "Tellstick tempsensor updated"
when
    Item TellstickTemperature1_ActualTemperature received update
then

    if(ZWaveMultiSensor_SensorTemperature.state == NULL ||
        TellstickTemperature1_ActualTemperature.state < ZWaveMultiSensor_SensorTemperature.state) {
        postUpdate(Utetemperatur, TellstickTemperature1_ActualTemperature.state)
    }

    var DateTime time1 = new DateTime(now)

    if(timer_t==null) {
        timer_t = createTimer(now.plusMinutes(5)) [|
            postUpdate(TellstickTemperature1_ActualTemperature, NULL)
            sendMail("removed_address", "Fel på tempsensor t", "Har inte fått något värde ifrån sensorn på verandan sedan " + time1.toString)
        ]
    } else {
        timer_t.reschedule(now.plusMinutes(5))
    }

end

rule "Z-Wave tempsensor updated"
when
    Item ZWaveMultiSensor_SensorTemperature received update
then

    if(TellstickTemperature1_ActualTemperature.state==NULL ||
        ZWaveMultiSensor_SensorTemperature.state < TellstickTemperature1_ActualTemperature.state) {
        postUpdate(Utetemperatur, ZWaveMultiSensor_SensorTemperature.state)
    }

    var DateTime time1 = new DateTime(now)

    if(timer_z==null) {
        timer_z = createTimer(now.plusMinutes(11)) [|
            postUpdate(ZWaveMultiSensor_SensorTemperature, NULL)
            sendMail("removed_address", "Fel på tempsensor z", "Har inte fått något värde ifrån sensorn på uteplatsen sedan " + time1.toString)
        ]
    } else {
        timer_z.reschedule(now.plusMinutes(11))
    }
end

Something is still wrong though, when the file is reloaded I get the following in my log:

2017-02-13 21:32:56.487 [ERROR] [org.quartz.core.ErrorLogger         ] - Job (DEFAULT.2017-02-13T21:02:56.226+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
  postUpdate(<XFeatureCallImplCustom>,<XFeatureCallImplCustom>)
  sendMail(<XStringLiteralImpl>,<XStringLiteralImpl>,<XBinaryOperationImplCustom>)
} ] threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.RuntimeException: The name '<unkown>' cannot be resolved to an item or type.]

(followed by a stacktrace) I don’t really know what it’s talking about, what is ?

Dunno, not an OH2 user.

I think you ought to have the timer(s) null itself on completion. They do not do that automatically, and your code will get in the situation of trying to reschedule an expired timer, which I think will fail.

Ok, I tried adding “timer_z=null” and “timer_t=null”, doesn’t make any difference. Also it seems like this error is thrown not when the timer is executed but rather when it’s declared. I always get it once for every time the rules file is refreshed…

You shouldn’t be doing the joda import in OH2, and this is known to cause problems. I’m not sure about the Timer.

Just to avoid suprises, I would explicitly declare these as null to begin with
var Timer timer_t = null
though that shouldn’t fix anything.

Oh. All examples have the imports, so I thought they were needed. I removed both of them now and they doesn’t seem to make any difference (everything works and I still get the same errors in the log).

When initializing the pointers to null I got an additional error about “Unable to store Job … because one already exists with this identification”. I assume that is because the timer already exists and by setting the timer_z variable to null I just lose my pointer to it, can that be the case? I wish I had a good way to check which timers actually exist, it’s hard to debug those lingering things otherwise…

At the moment you need to take great care about applying the much more numerous examples for OH1 to OH2

You’d better reiterate exactly what errors you get, and when.

Errors after a rules file reload are entirely expected in this case. You will almost certainly have timers running at reload time, which get orphaned, and they will almost certainly error when they complete because their context will have been destroyed

.[quote=“DanielMalmgren, post:10, topic:22815”]“Unable to store Job … because one already exists with this identification”.
I assume that is because the timer already exists and by setting the timer_z variable to null I just lose my pointer to it, can that be the case?
[/quote]
But your code should not be trying to create a new timer unless the old handle is null, so that’s a clue.

Keep seeing posts about OH2 users having phantom items and two ghostly sets of rules

Yes, but if I have a handler that actually is referencing a timer and then I first assign the handler null (ie the timer still exists, only now I have no pointer to it) and then create a new timer and assign it to the handler, than I’ll have this problem…

I’m starting to think my main problem here is that my Z-Wave sensor always sends it’s readings two times. So I get two calls to this rule at almost exact same time and there is a race condition. If one of the calls checks if timer_z=null and don’t get to assign it before the other one does the same check there’ll be a problem. I don’t have any of these problems with the “sister rule” using a Tellstick sensor. Maybe I just need to find out a way to do all the timer stuff in one transaction without being interrupted. Maybe some semaphore function?

that’ll be a reentrant lock

1 Like

Yep. With a lock() and unlock() everything works like a charm. It would be nice if the ZWave binding didn’t even let these simultaneous readings get through…

Anyway, I’ve now perfected my rule to make a “virtual” temperature sensor that works even if either my Z-Wave networks is down or if my Tellstick dies. Or if the sun shines on either of the sensors. Would it be a good idea to post it somewhere to help others? Ping @rlkoshak

Well spotted for the sneaky double trigger.

Yep, post in examples, more than one useful idea and tip incorporated in this now.

Examples are very welcome. If to think you have something that is genetically applicable to lots of different problems a design pattern posting is welcome. Otherwise an example with lots of notes would be great.

Do you really need the rule to fire on every update? You could also eliminate double execution and the lock if you change the trigger to changed instead of received update it should ignore the second update.

When ever I experience errors like these I try to see if I can change the rule triggers to solve the problem if possible. It simplifies the logic considerably.

I’m quite sure I want it to trigger on updates or I’ll get warning e-mails every time the temperature in fact is stable, won’t I? The point here is that I want to be alarmed if the sensor isn’t reporting anything at all (ie no updates), not if the sensor isn’t reporting any changes :slight_smile:

Although a temperature reading that never fluctuates is almost certainly a fault too … I can feel another rule coming on :wink:

True, true… Five minutes with a steady temperature doesn’t seem like a problem though but five minutes without the sensor communicating is. So yes, I guess we’d need another rule :smile:

Sorry for the terse replies. I’m on travel with just my phone.

Here is what I would do to implement what you are after, now that understand what you are doing.

I’d configure my Items to use the Expire binding to set them to NULL if they do not receive an update after your timeout period.

Then have a rule that triggers when the temps change to NULL and send your email.

No locks, no Timers, and you will get an alert when the Item fails to update for that time period.

I really am a fan of the Expire binding. It greatly simplefies these sorts of rules.