Not sure if this helps, but here you go:
- I don’t see where you are actually setting your stop-switch
- also the logic
if(!lock_GZL.isLocked && Sonoff_STOP.state != ON)
will fail if you never got a lock; and by fail I mean execute multiple times
The latter issue, simply not getting a lock in time, perplexed me quite a bit some a year or two ago, here is how I am structuring my rules
rule "MyRule"
when
// trule triggers go here
then
var gotLock = lock.tryLock(1000, TimeUnit.MILLISECONDS)
try {
if (gotLock) {
// do stuff here
}
else logInfo("MyRule", "re-entry lock activated")
}
finally {
if(gotLock){
lock.unlock()
}
}
end
here are some additional considerations/explanations:
- if it works you can probably get rid of your thread::sleep statements
- see here for for some more details: Design Pattern: Rule Latching
- this line:
var gotLock = lock.tryLock(1000, TimeUnit.MILLISECONDS)
makes the system essentially behave a little nicer (the value 1000 does not seem to matter, 0 will do too, see post linked above) - doing so you will simply drop events, but I guess that is exactly what you want; just stating this for clarity
- now to the real problem:
– in certain conditions your rule may die while in thetry{}
block and never execute thefinally {}
statement releasing the lock;
– when this happens, your rule will never execute thetry{}
block again as the lock will still be set;
– where this is becoming a real issue in my case is during start up where a rule may execute before items are defined or even the rule parser is fully up and running and I am seeing syntax errors that are not real syntax errors but some artefact during system start and Null pointer exceptions; when this happens the rule will abort and the lock will not be released.
– if you apply one of the many tricks that will run your rules only after everything else started up well (e.g, “preferred version” from here: Cleaning up the startup process / renaming rules (windows possible)), it will however work like a charm.
– Finally, be forewarned already in case you are reading the JAVA docs on concurrency guards, this whole mechanism of concurrency guard is implemented only implemented to a limited extent in the DSL; while JAVA offers here error catching and handling, this will not work well in DSL and not at all for NPE or syntax errors; (hence it is not implemented above); I tried… and others on the forum too, it is not worth the efforts as only very few errors are caught; you will need to take extra care in coding