Repository: blakeblackshear/frigate

Issue:
Event is not immediately sent when an object enters zone
**Describe the bug**
My goal is to perform a Home Assistant automation as soon as a person walks into a zone.

If the person is tracked, but outside the zone, then enters the zone, I noticed that no event is sent immediately.  It's sent a few seconds after I expected it.

Camera name is front_yard.  Zone is front_property.

Home Assistant log with my annotations:
:12  event with {type=new, before/after: current_zones": [], "entered_zones": []} is received.  The person is tracked, but not in any zone.  This is ok.

```
2021-06-30 20:20:12 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/events: 
b'{"before": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109612.245397, "label": "person", "top_score": 0.0, "false_positive": true, "start_time": 1625109612.245397, "end_time": null, "score": 0.76953125, "box": [580, 74, 609, 170], "area": 2784, "region": [404, 0, 704, 300], "current_zones": [], "entered_zones": [], "thumbnail": null}, 
"after": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109612.642196, "label": "person", "top_score": 0.76953125, "false_positive": false, "start_time": 1625109612.245397, "end_time": null, "score": 0.76953125, "box": [572, 79, 600, 179], "area": 2800, "region": [404, 0, 704, 300], "current_zones": [], "entered_zones": [], "thumbnail": null}, 
"type": "new"}'
```

:13 frigate/front_property/person count is 1, meaning person as entered the front_property zone, but no 'update' event is received:
```
2021-06-30 20:20:13 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/front_yard/person/snapshot: b'\xff'
2021-06-30 20:20:13 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/front_yard/person: b'1'
2021-06-30 20:20:13 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/front_property/person: b'1'
```
:18  update event is received 5 seconds after person has entered zone.  Now, the Home Assistant automation runs
```
2021-06-30 20:20:18 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/events: 
b'{"before": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109612.642196, "label": "person", "top_score": 0.76953125, "false_positive": false, "start_time": 1625109612.245397, "end_time": null, "score": 0.76953125, "box": [572, 79, 600, 179], "area": 2800, "region": [404, 0, 704, 300], "current_zones": [], "entered_zones": [], "thumbnail": null}, 
"after": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109617.642331, "label": "person", "top_score": 0.787109375, "false_positive": false, "start_time": 1625109612.245397, "end_time": null, "score": 0.75390625, "box": [580, 114, 641, 366], "area": 15372, "region": [404, 72, 704, 372], "current_zones": ["front_property"], "entered_zones": ["front_property"], "thumbnail": null}, 
"type": "update"}'

2021-06-30 20:20:18 INFO (MainThread) [homeassistant.components.automation.person_in_zone_front_property] person-in-zone-front_property: Running automation actions
2021-06-30 20:20:18 INFO (MainThread) [homeassistant.components.automation.person_in_zone_front_property] person-in-zone-front_property: Executing step call service
2021-06-30 20:20:18 INFO (MainThread) [homeassistant.components.automation.person_in_zone_front_property] person-in-zone-front_property: Executing step call service
2021-06-30 20:20:19 INFO (MainThread) [homeassistant.components.mobile_app.notify] mobile_app push notification rate limits for motoe: 4 sent, 500 allowed, 0 errors, resets in 20:39:40
2021-06-30 20:20:19 INFO (MainThread) [homeassistant.components.automation.person_in_zone_front_property] person-in-zone-front_property: Executing step delay 0:01:00

2021-06-30 20:20:23 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/events: 
b'{"before": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109617.642331, "label": "person", "top_score": 0.787109375, "false_positive": false, "start_time": 1625109612.245397, "end_time": null, "score": 0.75390625, "box": [580, 114, 641, 366], "area": 15372, "region": [404, 72, 704, 372], "current_zones": ["front_property"], "entered_zones": ["front_property"], "thumbnail": null},
 "after": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109623.242594, "label": "person", "top_score": 0.8125, "false_positive": false, "start_time": 1625109612.245397, "end_time": null, "score": 0.74609375, "box": [610, 78, 637, 177], "area": 2673, "region": [404, 0, 704, 300], "current_zones": [], "entered_zones": ["front_property"], "thumbnail": null}, 
"type": "update"}'
2021-06-30 20:20:23 INFO (MainThread) [homeassistant.components.automation.person_in_zone_front_property] person-in-zone-front_property: Already running
2021-06-30 20:20:23 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/front_property/person: b'0'

2021-06-30 20:20:29 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on frigate/events: 
b'{"before": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109623.242594, "label": "person", "top_score": 0.8125, "false_positive": false, "start_time": 1625109612.245397, "end_time": null, "score": 0.74609375, "box": [610, 78, 637, 177], "area": 2673, "region": [404, 0, 704, 300], "current_zones": [], "entered_zones": ["front_property"], "thumbnail": null}, 
"after": {"id": "1625109612.245397-d8w9b3", "camera": "front_yard", "frame_time": 1625109624.447229, "label": "person", "top_score": 0.8125, "false_positive": false, "start_time": 1625109612.245397, "end_time": 1625109629.642752, "score": 0.57421875, "box": [647, 86, 665, 143], "area": 1026, "region": [404, 0, 704, 300], "current_zones": [], "entered_zones": ["front_property"], "thumbnail": null}, 
"type": "end"}'
```


The docs say 
> When frigate finds a better snapshot of the tracked object or when a zone change occurs, it will publish a message with the same id.
so I thought I should get an 'type: update' event when the person entered the zone at :13.

Maybe it didn't send one because of the score?

In any case, I could use the frigate/front_property/person: b'1'  topic instead if it's as expected.



**Version of frigate**
0.8.4-5043040

**Config file**
<details>
  <summary>Click to expand</summary>

```yaml
mqtt:
  host: mqtt
  user: x
  password: '{FRIGATE_MQTT_PASSWORD}'
detectors:
  cpu1:
    type: cpu
  cpu2:
    type: cpu
cameras:
  front_yard:
    ffmpeg:
      inputs:
        - path: rtsp://user:{FRIGATE_RTSP_PASSWORD}@192.168.10.41:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
            - rtmp
        - path: rtsp://user:{FRIGATE_RTSP_PASSWORD}@192.168.10.41:554/cam/realmonitor?channel=1&subtype=0
          roles:
            - clips
            - record
      # added tag hvc1 for Safari browser playback
      input_args: -avoid_negative_ts make_zero -fflags +genpts+discardcorrupt -rtsp_transport tcp -stimeout 5000000 -use_wallclock_as_timestamps 1 -tag:v hvc1
      ## remove -an from record to keep audio
      #output_args:
      #  detect: -f rawvideo -pix_fmt yuv420p
      #  record: -f segment -segment_time 60 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c copy
      #  clips: -f segment -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c copy
      #  rtmp: -c copy -f flv

    width: 704
    height: 480
    fps: 5
    best_image_timeout: 10
    clips:
      enabled: true
      pre_capture: 5
      post_capture: 10
    record:
      enabled: true
      retain_days: 3
    snapshots:
      enabled: true
    objects:
      filters:
        person:
          # better night detection possibly due to using slow cpu detector
          min_score: 0.4
          threshold: 0.5
    motion:
      # better settings for motion detect from issue #1176
      frame_height: 180
      mask:
        - 704,58,704,0,0,0,0,211,410,135
    zones:
      front_property:
        coordinates: 0,480,704,480,633,328,689,156,0,395
```
</details>

**Frigate container logs**
```
none
```

**Frigate stats**
<details>
  <summary>Click to expand</summary>

```json
{
  "detection_fps": 0.0, 
  "detectors": {
    "cpu1": {
      "detection_start": 0.0, 
      "inference_speed": 137.12, 
      "pid": 34
    }, 
    "cpu2": {
      "detection_start": 0.0, 
      "inference_speed": 135.99, 
      "pid": 36
    }
  }, 
  "front_yard": {
    "camera_fps": 5.0, 
    "capture_pid": 40, 
    "detection_fps": 0.0, 
    "pid": 39, 
    "process_fps": 5.1, 
    "skipped_fps": 0.0
  }, 
  "service": {
    "storage": {
      "/dev/shm": {
        "free": 66.0, 
        "mount_type": "tmpfs", 
        "total": 67.1, 
        "used": 1.1
      }, 
      "/media/frigate/clips": {
        "free": 108734.3, 
        "mount_type": "ext4", 
        "total": 282845.1, 
        "used": 159668.5
      }, 
      "/media/frigate/recordings": {
        "free": 108734.3, 
        "mount_type": "ext4", 
        "total": 282845.1, 
        "used": 159668.5
      }, 
      "/tmp/cache": {
        "free": 934.2, 
        "mount_type": "tmpfs", 
        "total": 1000.0, 
        "used": 65.8
      }
    }, 
    "uptime": 87708, 
    "version": "0.8.4-5043040"
  }
}
```
</details>

**FFprobe from your camera**

```
n/a
```

**Screenshots**


**Computer Hardware**
 - OS: debian
 - Install method: Docker Compose
 - Virtualization: None
 - Coral Version: None
 - Network Setup: Wired

**Camera Info:**
 - Manufacturer: Dahua
 - Model: 
 - Resolution: 4k main, 704x480 substream
 - FPS: 5 substream for detection

**Additional context**




Discussion:
Great work, by the way.  Thank you, Blake, for creating and sharing Frigate with everyone.
That's because of the way I am rate limiting the mqtt messages, but I don't like it. 

Resolving patch:
diff --git a/frigate/object_processing.py b/frigate/object_processing.py
--- a/frigate/object_processing.py
+++ b/frigate/object_processing.py
@@ -107,6 +107,7 @@ def compute_score(self):
 
     def update(self, current_frame_time, obj_data):
         significant_update = False
+        zone_change = False
         self.obj_data.update(obj_data)
         # if the object is not in the current frame, add a 0.0 to the score history
         if self.obj_data["frame_time"] != current_frame_time:
@@ -152,10 +153,10 @@ def update(self, current_frame_time, obj_data):
 
         # if the zones changed, signal an update
         if not self.false_positive and set(self.current_zones) != set(current_zones):
-            significant_update = True
+            zone_change = True
 
         self.current_zones = current_zones
-        return significant_update
+        return (significant_update, zone_change)
 
     def to_dict(self, include_thumbnail: bool = False):
         snapshot_time = (
@@ -451,7 +452,9 @@ def update(self, frame_time, current_detections, motion_boxes, regions):
 
         for id in updated_ids:
             updated_obj = tracked_objects[id]
-            significant_update = updated_obj.update(frame_time, current_detections[id])
+            significant_update, zone_change = updated_obj.update(
+                frame_time, current_detections[id]
+            )
 
             if significant_update:
                 # ensure this frame is stored in the cache
@@ -464,11 +467,12 @@ def update(self, frame_time, current_detections, motion_boxes, regions):
                 updated_obj.last_updated = frame_time
 
             # if it has been more than 5 seconds since the last publish
-            # and the last update is greater than the last publish
+            # and the last update is greater than the last publish or
+            # the object has changed zones
             if (
                 frame_time - updated_obj.last_published > 5
                 and updated_obj.last_updated > updated_obj.last_published
-            ):
+            ) or zone_change:
                 # call event handlers
                 for c in self.callbacks["update"]:
                     c(self.name, updated_obj, frame_time)


Test patch: