Tutorial to Reduce False Alarms with IP Camera Motion Detection

I have a Hikvision PTZ camera which has a field of vision down my driveway in front of my house. I wanted to setup my camera in such a way that when someone comes up my driveway (either on foot or by car), a motion event is triggered and I am notified by text message. I found that using smart events alone resulted in far too many false alarms in spite of spending a fair amount of time trying many different settings combinations.

I then decided to integrate my z-wave motion activated flood light (also in my driveway) with the PTZ camera whereby in order to initiate an event BOTH the flood light PIR sensor and the camera motion sensor must be triggered by a motion event. In this way, 2 independent sensors are used and the hope was that false alarms would be reduced.

I found that that by doing this, I have virtually eliminated all false alarms and the system to notify me of a person or a car in my driveway works very well.

I am now offering this example to help others.

Equipment:

Bindings:

  • IpCamera - to detect camera smart events. I use the linecross smart event.

  • Z-Wave – to use the PIR sensor on the floodlight sensor to detect motion.

  • SMTP – to send email to text messages to notify me of events.

OPTION – If you use Synology’s Surveillance Station, alternatively you can also use the synologysurveillancestation binding to detect smart events from your camera rather than the IPcamera binding. I have found that both bindings work fine.

Here is how it works.

Create switch items for both the IpCamera linecross event and the z-wave floodlight PIR motion event that are enabled (turned to ON) when each one detects motion. The key is to use the ‘expiration’ feature so that each switch remains ‘ON’ for a defined period of time after it detects motion. I use 59 seconds. You can play with this to find a value that works for you.

A rule is create for each event and is triggered when motion is detected by the camera or the flood light. When triggered, the rule checks if the OTHER switch is also ‘ON’. Since you don’t know which sensor will be triggered first, you need a rule for each sensor and it checks if the other switch is also ‘ON’. If BOTH switches are on, then I am notified by text message that motion has been detected in my driveway.

I hope someone can find this useful. It works for me.

Here is the code:

The code consists of 2 rules, one for each sensor. You will also need to create 3 items, PTZ_LineCrossStatus, Flood_Driveway_Motion and DrivewayMotionDetected. See comments in the code below.

rule "PTZ Camera has detected line cross"
when
   /* PTZ_LineCrossStatus - a switch item (with 59 second expiration) that is linked to the 
      'Line Crossing Alarm' channel of the IPcamera binding   */
   
   Item PTZ_LineCrossStatus changed from OFF to ON or   
   Item PTZ_LineCrossStatus changed from  NULL to ON
then 
   
   /* If PTZ_LineCrossStatus changes to ON, then a check is made as to whether Flood_Driveway_Motion is also ON. 
      If so, and DrivewayMotionDetected has not already been triggered by the other sensor within the last 3
	  minutes, then a text notification is sent  */   
   
   if (Flood_Driveway_Motion.state == ON  && DrivewayMotionDetected.state != ON)
   
     { 
       val mailActions = getActions("mail","mail:smtp:gmailsmtp")
       mailActions.sendMail("905xxxyyyy@txt.bell.ca","Message from OpenHab","Driveway Motion Detected")          

       /* DrivewayMotionDetected - a motion event triggered by both sensors has been initiated. This is needed so another
          event triggered by the other sensor does not subsequently follow. Uses 180 second Expiration timer. */
          
       DrivewayMotionDetected.sendCommand(ON)
     }
end



rule "Flood_Driveway_Motion is ON"
when
   /* Flood_Driveway_Motion - a switch item (with 59 second expiration) that is linked to the 
      Motion Alarm 'alarm_motion' channel of the IPcamera binding   */

  Item Flood_Driveway_Motion changed from OFF to ON or
  Item Flood_Driveway_Motion changed from NULL to ON
  
then

   /* If Flood_Driveway_Motion changes to ON, then a check is made as to whether PTZ_LineCrossStatus is also ON. 
      If so, and DrivewayMotionDetected has not already been triggered by the other sensor within the last 3
	  minutes, then a text notification is sent  */   

  if (PTZ_LineCrossStatus.state == ON && DrivewayMotionDetected.state != ON) 
  
   { 
     val mailActions = getActions("mail","mail:smtp:gmailsmtp")
     mailActions.sendMail("905xxxyyyy@txt.bell.ca","Message from OpenHab","Driveway Motion Detected")
       
     /* DrivewayMotionDetected - a motion event triggered by both sensors has been initiated. This is needed so another
        event triggered by the other sensor does not subsequently follow. Uses 180 second Expiration timer. */
	 
	 DrivewayMotionDetected.sendCommand(ON)  
   }   
end
2 Likes

Nice work! Thanks for sharing.

I do something similar for my driveway & porch. I too have a Hikvision NVR (using the motion area & line crossing alarms), and Hue motion sensor on my porch facing the front door and use the astro day & night data to trigger various changes to lights if movement is detected at different times. I also consider if someone is at home or not via our presence items, using Owntracks, iBeacons & network binding for when the phones connect. I haven’t quite figured our how to detect presence via the Hue binding yet and would like to also use the iCloud binding and GPS coordinates as another indication of presence.

var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.Rules.Experiments");
var ScriptExecution = Java.type("org.openhab.core.model.script.actions.ScriptExecution");
var NotificationAction = org.openhab.io.openhabcloud.NotificationAction;

var lineCrossing = itemRegistry.getItem('Hikvision_LineCrossingAlarm_ANTIFLAP').getState();
var hikMotion = itemRegistry.getItem('HikvisionCamerawithAPI_MotionAlarm').getState();
var porchMotion = itemRegistry.getItem('Huemotionsensor2_Motion').getState();
var night = itemRegistry.getItem('Night_time').getState()
var day = itemRegistry.getItem('Day_time').getState()
var garageDoor = itemRegistry.getItem('ZWaveNode009_GarageDoor_DoorSensor').getState();
var someOneHome = itemRegistry.getItem('Someone_is_home').getState();
var ledsBackDoor = itemRegistry.getItem('OurLEDs1_Color').getState();
var ledsKitchen = itemRegistry.getItem('Huelightstrip_Color').getState();


//logger.info('Hikvision motion = ' + hikMotion);
//logger.info('Porch motion = ' + porchMotion);
//logger.info('Night time is ' + night);
//logger.info('Day time is ' + day);
//logger.info('Garage door is ' + garageDoor);
//logger.info('Someone is home? ' + someOneHome);
//logger.info('LEDs Back door ' + ledsBackDoor);
//logger.info('LEDs Kitchen ' + ledsKitchen);

//
// Day activity
//
if (hikMotion == 'ON' && porchMotion == 'ON' && lineCrossing == 'ON' && day == 'ON' && someOneHome == 'ON' && garageDoor == 'CLOSED')
{
logger.info('Line crossing & Porch front door!');
NotificationAction.sendBroadcastNotification('Line crossing & Porch front door!');
}
else if (hikMotion == 'ON' && porchMotion == 'ON' && day == 'ON' && someOneHome == 'ON' && garageDoor == 'OPEN') 
{
logger.info('Front movement detected but someone home & garage open. Its likely us.');
}
else if (hikMotion == 'ON' && porchMotion == 'ON' && day == 'ON' && someOneHome == 'OFF' && garageDoor == 'CLOSED')
{
NotificationAction.sendBroadcastNotification('Front door movement, no one home!');
logger.info('Front door movement, no one home!');
}
else if (hikMotion == 'ON' && lineCrossing == 'ON' && day == 'ON' && someOneHome == 'OFF' && garageDoor == 'CLOSED')
{
NotificationAction.sendBroadcastNotification('Front movement, no one home!');
logger.info('Front movement, no one home!');
}
//
// Night activity
//
else if (hikMotion == 'ON' && porchMotion == 'ON' && night == 'ON' && someOneHome == 'ON') 
{
NotificationAction.sendBroadcastNotification('Night & movement detected!!!');
logger.info('MOTION! Night & someone home');
events.sendCommand('ZWaveNode007IlluminatorFrontGarden_Dimmer', "100");
events.sendCommand('HuecolorlampFrontPatio_Color', "37,63,80");
events.sendCommand('HuecolorlampFrontPatio_ColorTemperature', "60");
events.sendCommand('Huelightstrip_Color', "0,100,80");                            // Send LEDs RED for 7 seconds then return to previous state.
events.sendCommand('OurLEDs1_Color', "0,100,80");
java.lang.Thread.sleep(7000);
events.sendCommand('Huelightstrip_Color', ledsKitchen);
events.sendCommand('OurLEDs1_Color', ledsBackDoor);
}
else if(hikMotion == 'ON' && porchMotion == 'ON' && night == 'ON' && someOneHome == 'OFF' && garageDoor == 'CLOSED') //&& lineCrossing == 'ON'
{
NotificationAction.sendBroadcastNotification('Night, movement & away!');
logger.info('MOTION! Night & noone home');
events.sendCommand('ZWaveNode007IlluminatorFrontGarden_Dimmer', "100");
events.sendCommand('HuecolorlampFrontPatio_Color', "0,100,80");
events.sendCommand('HuecolorlampFrontPatio_ColorTemperature', "100");  
}
else 
{
logger.info('Not enough motion triggers, nothing to report.');  
}

Great write up, here’s a small suggestion to improve your code. Just use a single ITEM trigger.

Item PTZ_LineCrossStatus changed to ON (this covers both scenarios you have listed)

Best, Jay

Nice thorough write up, thanks.

Another way to do this would be with a group item. You can add both your motion switches to a single group, give that group a switch default type, and give it an aggregation function. In your case you would want something such as “All ON then ON else OFF”. Here’s what setting up an aggregation function looks like in the UI:


The group item now has a state that changes as the member items change. It will go from OFF to ON only once both member items have changed to ON.

This gives you two benefits:

  1. You can reduce your scripts to a single rule that just triggers on the change of the group item and you don’t have to check the status of the ‘other’ item.
  2. You can have as many switch items as you want in that group contributing to the state that triggers the rule (for example, if you only want notifications during the day, then just add a switch item that is ON during daylight hours to the group).

There is one other way to potentially reduce the multiple rules down to a single rule: port the rule to the UI. There you can add conditions to rules that will only allow the rule to run if all conditions are true. So, you could stack both item change triggers in the same rule, but also add two conditions each which checks that the state of one of the items is ON. Again, this way you don’t have to do the check of the item state inside the rule script.

You can even take these conditions one step further and add one for the DrivewayMotionDetected state. If you do that then you can reduce the script to just the mail action and turning on DrivewayMotionDetected item.

@JustinG

I was not aware of the group aggregation functions. I will dig into this a little. I like the idea of having this function controlled by one rule. The DrivewayMotionDetected item would end up being the group name if I am understanding this correctly.

Re: Rules UI - I have not spent a lot of time with the rules UI as of yet. It is on my list. I looked at it quickly when OH3 was introduced.

These are interesting ideas.

@George_Whitehouse

Looks similar to what I am doing - except for the hue lighting integration. Interesting. Since my PIR sensor is a floodlight, the light also comes on if it is dark when the PIR sensor detects motion. In my case both sensors also detect motion in daylight.

Presence detection - I have also thought about this a lot. I concluded that the easiest way to detect presence was to integrate with my home alarm system. We have a DSC system which happens to have an OH binding. When the alarm is ARMED, we are away. When we are at home, the alarm system is DISARMED. I integrate this into several OH scripts.

@jwiseman

Nice improvement.

thanks to all of you for the great feedback and interesting ideas! It has given me some things to think about.