Introduction

In Eagle Eye API V3, the /events API retrieves the detected events in the system. In general, events in a security system are any occurrence detected by the system using an algorithm or sensor. As an example, motion events are movements in a camera image.

Event types

The following table describes the event types that are currently supported by the /events API:

Event TypeNameDescription
een.deviceCloudStatusUpdateEvent.v1Device statusA new event of this type is created when a device's status changes. The event represents the span of time the device stays in the given state and a null endTimestamp indicates it was still in the given state when the event was retrieved
een.motionDetectionEvent.v1Motion DetectionA new event of this type is created when there is a motion in front of the camera. The event represents the span of time for which the motion happened and a null endTimestamp indicates that the motion was still ongoing when the event was retrieved
een.motionInRegionDetectionEvent.v1.yamlMotion In ROI DetectionA new event of this type is created when a motion is detected in a specific region of interest.
een.lprPlateReadEvent.v1License plate recognitionA new event of this type is created when the camera captures a license plate of a passing vehicle. It represents a single point in time.
een.loiterDetectionEvent.v1Loitering DetectionA new event of this type is created when an object remains in the scene longer than the specified time in the minimumDwellTimeSecattribute.
een.tamperDetectionEvent.v1Tampering eventUsed to generate an alert when someone is trying to block the camera's view or the image is greatly altered.
een.objectLineCrossEvent.v1Line Crossing DetectionA new event of this type is created when an object crosses the line specified in line: attribute.
een.objectIntrusionEvent.v1Intrusion DetectionA new event of this type is created when an object enters into the area specified in the area: attribute.

Note: More events are coming. Please stay tuned.

Retrieving information on a camera's events

This section describes the steps you need to follow to retrieve event information for a camera using the /event API.

Prerequisites

  • Login to your account and receive an access token.
  • Get our Base URL from the client setting API
  • Using the Cameras API retrieve a list of the connected cameras to the end user.
  • Pick the camera ID that you want to check for events.

Procedure

  1. Call the list /events endpoint.

Example:

curl --location '<base-URL>/api/v3.0/events?startTimestamp__gte=2023-05-19T11%3A30%3A15.418%2B00%3A00&endTimestamp__lte=2023-05-19T12%3A30%3A15.418%2B00%3A00&actor=camera%3A1004cb8c&pageSize=10&type__in=een.deviceCloudStatusUpdateEvent.v1&include=data.een.deviceCloudStatusUpdate.v1' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <access-token>'

πŸ“˜

Note

The startTimestamp gte and endTimestamp lte should be in [ISO 8601 format.

For example: 2023-05-15T11:30:15.418%2B00:00

An example response of an /events GET request:

{
    "nextPageToken": "",
    "prevPageToken": "",
    "results": [
        {
            "type": "een.deviceCloudStatusUpdateEvent.v1",
            "id": "1004cb8c-2023-05-19T11:30:15.418Z-een.deviceCloudStatusUpdateEvent.v1",
            "startTimestamp": "2023-05-19T11:30:15.418+00:00",
            "endTimestamp": null,
            "span": true,
            "accountId": "00098540",
            "actorId": "1004cb8c",
            "actorAccountId": "00098540",
            "actorType": "camera",
            "creatorId": "een.systemHealth",
            "dataSchemas": [
                "data.een.deviceCloudStatusUpdate.v1"
            ],
            "data": [
                {
                    "type": "een.deviceCloudStatusUpdateEvent.v1",
                    "creatorId": "een.systemHealth",
                    "newStatus": {
                        "connectionStatus": "online"
                    }
                }
            ]
        }
    ],
    "totalSize": 1
}

πŸ“˜

Note

Each event will have one or more dataSchemas associated with it. These dataSchemas provide additional information that can be requested with an event to gain more insight regarding an event. For instance, the following information can be available through dataSchemas:

  • Bounding boxes when an object is detected.
  • Event snapshot URL's for the event.
  • LPR data, such as license plate number, the bounding box of the license plate, and so on.
  • Additional information, such as upper body clothing color, people carrying backpack, and so on.

Users can request one or more dataSchemas with an event and based on whether the event has the dataSchemas, data will be returned.

Example:

If you include the type data.een.deviceCloudStatusUpdate.v1 in the include parameter of the API you will get the above result in the data field.

There are two more endpoints in the /events API:

  • api/v3.0/events:listFieldValues. This endpoint retrieves the types of event that are supported
  • api/v3.0/eventTypes?language=pg. This endpoint retrieves a description for each type of supported events.

Sample code

Here is a simple CLI tool that stores 10 images of the first 10 motion events following the start timestamp based on four inputs from the user. Images are stored in the c:/events/ folder.

Before you begin: Before running the code, make sure you have all the required (imported) libraries installed.

The four inputs are the following:

  1. access token
  2. Base_URL
  3. Camera ID
  4. Start timestamp

In the following example, the end timestamp is required in calling the /event endpoint, so the endTimestamp is calculated as 1 hour after the startTimestamp:

import requests
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
from urllib.parse import quote_plus
from datetime import timedelta
import time

BEARER = "Bearer "
EVENTS_DIR = "c:/events/"

def get_input(prompt):
    return input(prompt)

def get_data_from_api(session, url, headers):
    response = session.get(url, headers=headers)
    response.raise_for_status()
    return response.json()

def save_image_from_url(session, url, headers, file_path):
    retries = 5
    delay = 5
    for _ in range(retries):
        try:
            response = session.get(url, headers=headers, stream=True)
            print(response)
            response.raise_for_status()
            with open(file_path, 'wb') as out_file:
                out_file.write(response.content)
            return
        except requests.exceptions.HTTPError as err:
            if retries > 1:
                time.sleep(delay)  # wait before trying again
                retries -= 1
                continue
            else:
                raise err

def prepare_timestamps(start_timestamp_input):
    start_timestamp = parse(start_timestamp_input)
    start_timestamp_str = start_timestamp.isoformat().replace("+00:00", ".000%2B00:00")

    end_timestamp = start_timestamp + relativedelta(hours=1)
    end_timestamp_str = end_timestamp.isoformat().replace("+00:00", ".000%2B00:00")

    return start_timestamp_str, end_timestamp_str

def main():
    with requests.Session() as session:
        access_token = get_input("Enter Access Token: ")
        base_url = get_input("Enter Base URL: ")
        camera_id = get_input("Enter Camera ID: ")
        start_timestamp_input = get_input("Enter start timestamp (YYYY-MM-DDTHH:MM:SS.000Z): ")

        start_timestamp_str, end_timestamp_str = prepare_timestamps(start_timestamp_input)

        headers = {"Authorization": BEARER + access_token}
        url = f"https://{base_url}/api/v3.0/events?startTimestamp__gte={start_timestamp_str}&endTimestamp__lte={end_timestamp_str}&actor=camera:{camera_id}&pageSize=100"
        data = get_data_from_api(session, url, headers)

        motion_event_count = 0
        for result in data.get('results', []):
            if motion_event_count >= 10:
                break
            if result.get('creatorId') == "een.bridgeMotion":
                motion_start_timestamp = result.get('startTimestamp')
                if motion_start_timestamp:
                    timestamp_datetime = parse(motion_start_timestamp) + timedelta(milliseconds=500)
                    timestamp_str = timestamp_datetime.isoformat()
                    timestamp_url = quote_plus(timestamp_str)
                    image_url = f"https://{base_url}/api/v3.0/media/recordedImage.jpeg?deviceId={camera_id}&type=preview&timestamp__lt={timestamp_url}"
                    file_path = f"{EVENTS_DIR}{timestamp_str.replace(':', '-').replace('.', '-').replace('+', '-')}.jpg"
                    save_image_from_url(session, image_url, headers, file_path)
                    print(f"Saved image for timestamp {timestamp_str} to {file_path}")
                    motion_event_count += 1


if __name__ == "__main__":
    main()

πŸ“˜

Note

The startTimestamp of the motion events represents the moment when the bridge first detected the motion. The best view of the moving object is not necessarily available at this moment. To have a better shot of the moving object, a 500 millisecond time delta is added to the startTimestamp in line 67. Depending on your use case, you can adjust this time.

πŸ“˜

Tip

You can retrieve the main image of the event if you change the type=preview to type=main in line 70.