How to deal with sensors sending signals in bursts

I’m struggling with some sensors (cheap rf 433 Mhz PIRs and door sensors). When triggered they send a burst of signals (can be 4 signals within a second) and they seem to be activating my rules “in parallel”. The items are coming from an mqtt broker which receives them from a NinjaBlock (beagle bone with arduino RF cape). Here’s what the logs pick-up:

2015-10-07 19:42:12.911 [INFO ] [runtime.busevents             ] - Front_door_sensor state updated to OPEN
2015-10-07 19:42:15.973 [INFO ] [runtime.busevents             ] - Front_door_sensor state updated to OPEN
2015-10-07 19:42:16.145 [INFO ] [runtime.busevents             ] - Front_door_sensor state updated to OPEN
2015-10-07 19:42:16.445 [INFO ] [runtime.busevents             ] - Front_door_sensor state updated to OPEN
2015-10-07 19:42:16.645 [INFO ] [runtime.busevents             ] - Front_door_sensor state updated to OPEN
2015-10-07 19:42:16.736 [INFO ] [runtime.busevents             ] - Front_door_sensor state updated to OPEN
2015-10-07 19:42:18.149 [INFO ] [rg.openhab.model.script.rules] - Front door open!!
2015-10-07 19:42:31.649 [INFO ] [rg.openhab.model.script.rules] - Front door open!!
2015-10-07 19:42:53.769 [INFO ] [rg.openhab.model.script.rules] - Front door open!!
2015-10-07 19:43:24.252 [INFO ] [rg.openhab.model.script.rules] - Front door open!!
2015-10-07 19:43:36.750 [INFO ] [rg.openhab.model.script.rules] - Front door open!!
2015-10-07 19:43:50.451 [INFO ] [rg.openhab.model.script.rules] - Front door open!!

As you can see this is all happening very quickly and the door was opened once. This sensor only triggers on opening and does not report state. When closed no signal is sent.

I’ve tried several things for the rules, like defining a boolean for the state of the door, or locking the thread, but I’m still getting up to 10 emails per door opening…

Here’s one version of the rules I’ve tried:

    rule “send email when front door open”
	    when
	    	Item Front_door_sensor received update
	    then
	    	lock.lock()
	    	try{
	    			logInfo(“rules”, “Front door open!!”)
	    			sendMail(“my.email.address”, “someSubject”, “emailBodyText”, “image url“)
	    			front_door_timer = createTimer(now.plusSeconds(30)) [|
	              		// wait so that a burst of triggers only sends one email
	              	]
			}finally{
				lock.unlock()
			}
end

The item definition is:

Contact Front_door_sensor "Front door" (groundFloor) {
	mqtt="<[mosquitto:ninjaCape/input/11/0:state:OPEN:010101010000111101010100]"
}

I’ve also set debug level on the logs for mqtt, here’s the output for an door opening event:

2015-10-07 23:30:44.732 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:44.734 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:44.735 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001010101010101010101' does not apply.
2015-10-07 23:30:44.737 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:44.739 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:44.741 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:44.902 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:44.903 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:44.905 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001010101010101010101' does not apply.
2015-10-07 23:30:44.906 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:44.909 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:44.910 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:45.132 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:45.134 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:45.135 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001010101010101010101' does not apply.
2015-10-07 23:30:45.137 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:45.139 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:45.140 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:45.261 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:45.263 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:45.264 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001010101010101010101' does not apply.
2015-10-07 23:30:45.266 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:45.268 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:45.270 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:45.441 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:45.443 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:45.445 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001010101010101010101' does not apply.
2015-10-07 23:30:45.446 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:45.448 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:45.450 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:45.613 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:45.614 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:45.615 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001010101010101010101' does not apply.
2015-10-07 23:30:45.617 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:45.619 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:45.620 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010101010000111101010100' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:52.852 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:52.853 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:52.855 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:52.857 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010000111101010100' does not apply.
2015-10-07 23:30:52.858 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:52.859 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:53.028 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:53.030 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:53.112 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:53.114 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010000111101010100' does not apply.
2015-10-07 23:30:53.115 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:53.116 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:53.318 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:53.320 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:53.412 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:53.414 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010000111101010100' does not apply.
2015-10-07 23:30:53.415 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:53.416 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:53.435 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:53.436 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:53.438 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:53.440 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010000111101010100' does not apply.
2015-10-07 23:30:53.441 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:53.493 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000110011000000000000' does not apply.
2015-10-07 23:30:57.181 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010001' does not apply.
2015-10-07 23:30:57.242 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000000000010101010100' does not apply.
2015-10-07 23:30:57.263 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010101010100010101' does not apply.
2015-10-07 23:30:57.265 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010101010000111101010100' does not apply.
2015-10-07 23:30:57.266 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '010001111101010101010000' does not apply.
2015-10-07 23:30:57.267 [DEBUG] [.o.b.m.i.MqttMessageSubscriber] - Skipped message '010001010101010101010101' because Message Filter '000000110011000000000000' does not apply.

Any help is greatly appreciated!

You are almost there but some of the things you are trying to use don’t work the way you think they do.

The big thing is that createTimer doesn’t work the same way as Thread::sleep(30000). Thread::sleep(30000) will actually stop execution of the rule for 30 seconds before continuing. I think this is what you want based on your comment, but I don’t think it will work so lets move on.

I can see two ways to make this work. My preferred method would be to create another Proxy item to represent the front door which gets updated when the Front_door_sensor is triggered and create a timer to reset it after 30 seconds. Then use Front_door_sensor_proxy changed to ON to trigger your sendMail.

Items:

Contact Front_door_sensor "Front door" (groundFloor) {
	mqtt="<[mosquitto:ninjaCape/input/11/0:state:OPEN:010101010000111101010100]"
}
Contact Front_door_sensor_proxy "Front door" (groundFloor)

Rules:

val Timer front_door_timer = null

rule "Update the Front_door_sensor_proxy"
when
    Item Front_door_sensor received update
then
    if(Front_door_sensor_proxy.state != OPEN) Front_door_sensor_proxy.sendCommand(OPEN)
end

rule "Send email when door opened"
when
    Item Front_door_sensor_proxy changed to OPEN
then
    logInfo(“rules”, “Front door open!!”)
    sendMail(“my.email.address”, “someSubject”, “emailBodyText”, “image url“)
    front_door_timer = createTimer(now.plusSeconds(30), [|
        Front_door_sensor_proxy.sendCommand(CLOSED)
    ]
end

Personally I think this approach is cleaner and much easier to read and understand than the second approach. It also makes better use of the facilities available in openHAB.

The Second approach will be to adopt your existing attempt at writing the rule to make it work. What I think you want is to create a boolean that get set to true for the first receipt of the update and a timer to set it back to false after awhile. Unfortunately this isn’t super straight forward because the body of a timer has its own context and is unable to change the value of the boolean itself. But we can be sneaky.

Try something like this:

val java.util.concurrent.locks.ReentrantLock lock  = new java.util.concurrent.locks.ReentrantLock()
var Timer front_door_timer = null

rule "send email when front door open"
when
    Item Front_door_sensor received update
then
    try {
        lock.lock

        var bool sendMsg = false

        // No timer has ever been set, create one and send the email
        if(front_door_timer == null) {
            firstUpdate = false
            front_door_timer = createTimer(now.plusSeconds(30), [| 
                // do nothing
            ]
            sendMsg = true
        }

        // Timer has expired from last time door opened, treat this update as a new door opening
        else if(front_door_timer.hasTerminated) {
            front_door_timer.reschedule(now.plusSeconds(30)) // reset the timer
            sendMsg = true
        }
        
        // Email only gets sent if there isn't a timer running.
        if(sendMsg) {
            logInfo(“rules”, “Front door open!!”)
	    sendMail(“my.email.address”, “someSubject”, “emailBodyText”, “image url“) 
        }
    } finally {
        lock.unlock
    }
end
2 Likes

I’ve struggled with the same issues. Don’t use the Thread:sleep - ive tried to a few times and every time I end up “locking up” the rule engine. It seems like two or more rules can fire at once, then they both sleep, and it never wakes up…

I use your first method to stop the ‘double action’ like this -

 val java.util.concurrent.locks.ReentrantLock lock  = new java.util.concurrent.locks.ReentrantLock()

rule "send email when front door open"
when
    Item Front_door_sensor received update
then
     if( !lock.isLocked() ) 
     {
    	lock.lock()
    	try{
    			logInfo(“rules”, “Front door open!!”)
                            // do whatever you want
       }
           finally {
	    lock.unlock()
           }
    }
    else{
          logInfo("rules", "Ignoring second action")
    }

Note I just coded it in the browser from my rules as a reference, it looks correct, but didnt test it :wink:

1 Like

Just thinking out loud - would it work if you just changed your rule trigger to:

Item Front_door_sensor changed from CLOSED to OPEN

The theory being that if it receives an update when it’s already OPEN, that won’t trigger the rule.

@evans_jon, the problem is he said there is no signal for when the door closes so unless there is something else to change the contract back to closed this won’t work. My first approach above basically does what you recommend though through a proxy item.

I missed that. He could still do something like this:

rule "Door opened"
when
    Item Front_door_sensor changed from CLOSED to OPEN
then
    // TODO: send a message about "door open" or whatever
    createTimer(now.plusSeconds(30), [|
                // assume door is closed after 30 seconds
                sendCommand(Front_door_sensor, CLOSED)
                // TODO: send a message about "door closed" if needed
            ])
end

@rlkoshak
Thanks a lot for your help, your code works! However, initially I had two emails sent a couple of times, and I 've had weird behaviour, meaning rules not doing the same all the time, before. I wonder if heavy load can influence this…

@perrin, using your code I was still getting up to 10 emails per event. It doesn’t make sense to me!?? Thanks for your help.

@evans_jon, as @rlkoshak said my sensor doesn’t go from CLOSED to OPEN, it just issues a “Front_door_sensor state updated to OPEN”. I had tried code similar to the one you suggested without solving the problem.

Thanks to all

Which version of my suggestions did you implement, the proxy Item or just implemented in the rule?

The proxy works. The other one is very similar to things I tried and didn’t work, however, I did not try yours verbatim.

OK, it might be the case that the events are coming in so fast you have to put the lock back in.

Without logs I can’t say for sure but I’m guess that an event comes in and fires off the sendCommand on Front_door_sensor_proxy but before the event bus can finish process it (i.e. change the state of the proxy to OPEN) the rule gets triggered again and sends a second command.

Try putting a lock around the “if” in the “Update the Front_door_sensor_proxy” rule to keep more than one event from processing at the same time.

You can further separate the processing of the events if before you unlock to put in a Thread::Sleep(100) to give the event bus time to process the sendCommand before the rule gets processed again.

Hmm with my code it’s possible that it locks and unlocks so quickly that its possible it re-triggers, depending on what you’re processing in the rule. Maybe a Thread:sleep(500) inside the lock would be appropriate… Then it would only sleep once and additional rules wouldn’t fire off.

With the timer rule I posted which explicitly sets the door to CLOSED after 30 seconds, I think it would transition from CLOSED to OPEN on the next activation. You would probably also need a rule like this to set it to CLOSED on startup:

rule "Front_door_sensor starts off CLOSED"
when
    System started
then
    sendCommand(Front_door_sensor, CLOSED)
end

I am trying to find a solution for you which would avoid the need for locks / mutexes etc. :smile: