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?
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?
[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 ?
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…
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?
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
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
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