[SOLVED] Alarm by PM - double check

Hi,

I need an idea. The following rule leads to a false alarm if, for example, a calendar or a greeting card falls off the pinboard. I don’t want to change the sensitivity of the PMs. I now need an idea of how I can check within the rule whether the PM still detects movement after 3 seconds or whether it had detected movement again within this time after the first trigger.

rule "Alarmanlage PM"
when
    Item PM_Wohn_P4_Ueberwachung changed from CLOSED to OPEN or
	Item PM_Diele_P2_Ueberwachung changed from CLOSED to OPEN or
	Item PM_WC_P2_Ueberwachung changed from CLOSED to OPEN
then
	Thread::sleep(3000)
	if(Alarm_schalten.state == ON){
		postUpdate(Alarm_ausgeloest, ON)
		logInfo('ALARM', 'ALARM wurde durch PM ausgelöst!!!!')
	}
end

For those of us who are “German-impaired” a rough English translation of the rule could be useful :wink:

How do your sensors work? Do they stay OPEN all the time motion is occurring, or do they go OPEN for a short time only, maybe going OPEN again almost immediately for continuous movement?
It makes a difference as to what to trigger things from.

Given that the sensors are fast enough, you can simply test the sensors within the rule. But I suggest a more clever way to do it:

Group:Contact gUeberwachung
Contact PM_Wohn_P4_Ueberwachung "PM Wohn P4" (gUeberwachung) 
Contact PM_Diele_P2_Ueberwachung "PM Diele P2" (gUeberwachung) 
Contact PM_WC_P2_Ueberwachung "PM WC P2" (gUeberwachung) 

rule:

// Always set global vars at top of the file
var Timer tAlarm = null

rule "Alarmanlage PM"
when
    Member of gUeberwachung changed
then
    if(tAlarm!==null && gUeberwachung.members.filter[i|i.state != CLOSED].size == 0) {
        logInfo("alarm","detected false positive, abort alarm")
        tAlarm.cancel
    } else if(gUeberwachung.members.filter[i|i.state != CLOSED].size > 0) {
        logInfo("alarm","detected movement!")
        tAlarm?.cancel
        tAlarm = createTimer(now.plusSeconds(3),[|
            if(gUeberwachung.members.filter[i|i.state != CLOSED].size > 0 && Alarm_schalten.state == ON) {
                Alarm_ausgeloest.postUpdate(ON)
                logInfo("alarm", "ALARM wurde durch PM ausgelöst!")
            }
            tAlarm = 0
        ])
    }
end
1 Like

Finally i was able to learn a lot from the code of @Udo_Hartmann . But my solution looks a bit different. Especially because I wanted to check if there was any movement detected in a certain period of time.

var varAlarmPM = 1

//Triggering an alarm by motion detectors
rule "Alarmanlage PM"
when
	Member of gBewegungChart changed from CLOSED to OPEN
then
	//Check activation delay
	if(timer_Alarmverzoegerung !== null){
		logInfo("ALARM", "Movement sensor reports movement within 10 minutes after alarm ON. Forgetting something?")
	//Check if rule is already running
	}else if(varAlarmPM == 1 && Alarm_schalten.state == ON && Alarm_ausgeloest.state !== ON){
		varAlarmPM = 2
		gBewegungChart.members.filter(s|s.state == OPEN).forEach(i | logInfo("alarmPM", i.name + " initial movement detected!"))
		Thread::sleep(2000)
		// Check for 10 second if another movement occurs 2 second after first movement
		var ti = 1
		var varStop = 1
		while (ti < 20 && varStop == 1 && Alarm_schalten.state == ON && Alarm_ausgeloest.state !== ON){
			if(gBewegungChart.members.filter[i|i.state == OPEN].size > 0){
				Alarm_ausgeloest.postUpdate(ON)
				logInfo("alarmPM", "ALARM was triggered by PM")
				gBewegungChart.members.filter(s|s.state == OPEN).forEach(i | logInfo("alarmPM", i.name + " further movement detected!"))
				varStop = 2
			}else{
				logInfo("alarmPM", "No further movement detected. Probably only a fly. Run:" + ti)
			}
			ti=ti+1
			Thread::sleep(500)
		}
		varAlarmPM = 1
	}
end

Thank you all