Event and Vision Notification

Smarter AI platform libraries provide you necessary privileges to get Access control events such as Endpoint presence change event, Endpoint Info change event, Role change event and vision notifications. This section describes how you can subscribe and get these events and notifications using Access. All the methods used for demonstration in this section, are provided in Access.java and Access.h for respectively Android and iOS.

Getting Access Control Events

You can subscribe for Access Control related events such as Endpoint presence change, Endpoint info change and Role change events using Access library.

Endpoint Presence Change Events

📘

Android

  1. To get callback for endpoint presence change events, call enablePresenceChangeNotification() method from Access class once after Access build is successful.
AnyConnectApi.get().getAccess().enablePresenceChangeNotification();
  1. Then attach interface Access.EndpointPresenceChangeListener to Access by calling RegisterPresenceListener(EndpointPresenceChangeListener listener) method.
AnyConnectApi.get().getAccess().RegisterPresenceListener(endpointPresenceChangeListener);
  1. Once the interface is registered with Access, presence events of your Associated endpoints will start posting to the onPresenceChange(String endpointId, String label, Access.PresenceStatus status) method of your registered interface.
endpointPresenceChangeListener = new Access.EndpointPresenceChangeListener() {
        @Override
        public void onPresenceChange(String endpointId, String label, Access.PresenceStatus status) {
        // label is String representation of presence of the endpoint
        // status represents if endpoint is online or offline
        // See Access JavaDoc for more details about Access.PresenceStatus
    }
};

This method will get called every time when the presence of an endpoint associated to your account gets changed. The status can either be endpointOnline or endpointOffline according to the presence of the endpoint.

📘

iOS

  1. Call registerPresenceChangeCallback(PresenceChangeCallback callback) method of Access class to register presence change callback function.

Declaration of PresenceChangeCallback is:

typedef std::function<void(const Endpoint &endpointId,
                            std::string endpointLabel,
                            PresenceStatus status)> PresenceChangeCallback;

and definition of PresenceStatus type is:

typedef enum {
    endpointOnline,     ///< Endpoint is online
    endpointOffline,    ///< Endpoint is offline
} PresenceStatus;
  1. Once the callback is registered to Access library, you will start receiving presence events of associated endpoints linked to your account.
AccessRet accessRet = access->registerPresenceChangeCallback([self](const Endpoint &endpointId, const std::string endpointLabel, PresenceStatus status) {
        // endpointLabel is string representation of presence of the endpoint
        // status represents if endpoint is online or offline
        });

if (accessRet == OK) {
    //Registered presence change callback function successfully
} else {
    //Failed to register presence change callback function
}

This method will get called every time when the presence of an endpoint associated to your account gets changed. The status can either be endpointOnline or endpointOffline according to the presence of the endpoint.

Endpoint Info Change Events

📘

Android

  1. To get callback for endpoint info change events, call enableEndpointInfoChangeNotification() method from Access class once after Access build is successful.
AnyConnectApi.get().getAccess().enableEndpointInfoChangeNotification();
  1. Then, attach the interface Access.EndpointInfoChangeListener to Access by calling RegisterEndpointInfoChangeListener(EndpointInfoChangeListener listener) method of Access class.
AnyConnectApi.get().getAccess().RegisterEndpointInfoChangeListener(endpointInfoChangeListener);
  1. Once the interface is registered to Access, you will start receiving info change events of Associated endpoints linked to your account. These events are triggered when someone changes information of any of your associated endpoints. These events are posted to the onEndpointInfoChanged(Access.ChangedInfo info, String endpointId, String changedData) method of your registered interface.
endpointInfoChangeListener = new Access.EndpointInfoChangeListener() {
    @Override
    public void onEndpointInfoChanged(Access.ChangedInfo info, String endpointId, String changedData) {
            // info indicates which type of data has changed
            // changedData is a string containing the changed information of that endpoint
            // See Access JavaDoc for more details of Access.ChangedInfo
        }
    };

In onEndpointInfoChanged() method, the first parameter info indicates which type of data has changed for the endpoint. The second parameter indicates the endpointId. And the last changedData parameter, indicates the new data which has been assigned to the endpoint.

📘

iOS

  1. Call registerEndpointInfoChangeCallback(InfoChangeCallback callback) method of Access class to register endpoint info change callback function.

Declaration of InfoChangeCallback is:

typedef std::function<void(const ChangedInfo& info,
                            const Endpoint endpointId,
                        const std::string& changedData)> InfoChangeCallback;

and definition of ChangedInfo type is:

enum class ChangedInfo {
    Name,
    ImageURL,
    Ipv4Address,
    Ipv6Address,
    SDP,
    RecordingRelaySDP,
    Unknown ///Never use, only for internal purpose
};
  1. Once the callback is registered to Access library, you will start receiving info change events of Associated endpoints linked to your account.
    AccessRet accessRet = access->registerEndpointInfoChangeCallback([self](const ChangedInfo& info,
                                    const Endpoint endpointId, const std::string& changedData){
                // info indicates which type of data has changed
                // changedData is a string containing the changed information of that endpoint
            });

    if (accessRet == OK) {
        //Registered info change callback function successfully
    } else {
        //Failed to register info change callback function
    }

In callback method, the first parameter info indicates which type of data has changed for the endpoint. The second parameter indicates the endpointId. And the last changedData parameter, indicates the new data which has been assigned to the endpoint.

Endpoint Role Change Events (Add, Revoke & Update)

📘

Android

  1. To get callback for events of role changes, call enableRoleChangeNotification() method from Access class once after Access build is successful.
AnyConnectApi.get().getAccess().enableRoleChangeNotification();
  1. Then attach the interface Access.EndpointRoleChangeListener to Access by calling RegisterRoleChangeListener(EndpointRoleChangeListener listener) method.
AnyConnectApi.get().getAccess().RegisterRoleChangeListener(endpointRoleChangeListener);
  1. Once the interface is registered to Access, you will start receiving role change events of Associated endpoints linked to your account.
    These events are triggered when someone adds you to a new endpoint, changes your role or revokes you from any existing endpoint. These events are posted to the onRoleChange() method of your registered interface.
endpointRoleChangeListener = new Access.EndpointRoleChangeListener() {
    @Override
    public void onRoleChange(String endpointId, Access.PeerRole role, Access.PeerStatus status) {
        // role is the updated PeerRole assigned to you for the endpoint
        // status indicates add, revoke or update event
        // see Access JavaDoc for more details of PeerRole and PeerStatus
    }
};

In the onRoleChange() method, the first parameter indicates the endpointId of a particular endpoint where you have been added, revoked or your role has been updated. The second parameter role denotes the updated PeerRole assigned to you for that endpoint. The third parameter status defines if you are added, revoked or your role has been updated for the endpoint.

📘

iOS

  1. Call registerRoleChangeCallback(RoleChangeCallback callback) method of Access class to register role change callback function.

Declaration of RoleChangeCallback is:

typedef std::function<void(const Endpoint &endpointId,
                                PeerRole role,
                            PeerStatus peerStatus)> RoleChangeCallback;

and definition of PeerRole is:

typedef enum {
    Owner,              ///< Peer is an owner of this endpoint
    Admin,              ///< Peer is an admin of this endpoint
    Viewer,             ///< Peer is a viewer of this endpoint
    Unknown
} PeerRole;

definition of PeerStatus is:

enum class PeerStatus {
    Added,
    Existing,
    Removed,
    Unknown
};
  1. Once the callback is registered to Access library, you will start receiving role change events of Associated endpoints linked to your account.
AccessRet accessRet = access->registerRoleChangeCallback([self](const Endpoint &endpointId,
                                                                types::PeerRole role,
                                                                PeerStatus peerStatus) {
            // role is the updated PeerRole assigned to you for the endpoint
            // status indicates Added, Existing or Removed event
        });

if (accessRet == OK) {
    //Registered role change callback function successfully
} else {
    //Failed to register role change callback function
}

In the callback method, the first parameter indicates the endpointId of a particular endpoint where you have been added, removed or your role has been updated. The second parameter role denotes the updated PeerRole assigned to you for that endpoint. The third parameter status defines if you are added, removed or your role has been updated for the endpoint.

Getting Vision Notification

Smarter AI platform library provides you priviledges to subscribe and get vision notifications from your Smart AI enabled devices. There can be two types of vision notifications.

  • Vision Events : These types of notifications are triggered when a vision events are captured in the camera such as "A person has been detected", "A car has been detected", "Person taking selfie" etc

  • Sensor Events : These types of notifications are triggered when there occurs a sensor event in the camera.

📘

Android

  1. To categorize vision notifications, two types of Ids are defined for detecting vision events and sensor events.
public static final String MESSAGE_ID_VISION = "com.anyconnect.vision.app";
public static final String MESSAGE_ID_SENSOR_EVENT = "com.anyconnect.sensor.event";
  1. To enable callbacks for vision notification, call enableMessageNotification() from Access class once after Access build is successful for both vision events and sensor events.
AnyConnectApi.get().getAccess().enableMessageNotification(MESSAGE_ID_VISION);
AnyConnectApi.get().getAccess().enableMessageNotification(MESSAGE_ID_SENSOR_EVENT);
  1. Next, attach interface Access.ReceiveMessageListener to Access by calling RegisterMessageListener(ReceiveMessageListener listener) method.
AnyConnectApi.get().getAccess().RegisterMessageListener(receiveMessageListener);
  1. Once the interface is registered, you will start receiving vision notifications of your Associated endpoints. These notifications will be posted to onMessage(Access.MessageData data) method of your registered interface.
receiveMessageListener = new Access.ReceiveMessageListener() {
    @Override
    public void onMessage(Access.MessageData data) {
        // endpointId of the endpoint from where notification is sent
        String endpointId = data.remoteId;
        // defines notification type.
        // Compare with MESSAGE_ID_VISION or MESSAGE_ID_SENSOR_EVENT for getting the type
        String type = data.type;
        // Contains the notification text
        String notificationText = data.text;
    }
};

Each vision notification is wrapped as Access.MessageData and provided to the data parameter of onMessage method. The endpointId, type and the notificationText is provided in the data.

📘

iOS

  1. To categorize vision notifications, two types of Ids are defined for detecting vision events and sensor events.
#define MESSAGE_ID_VISION         "com.anyconnect.vision.app";
#define MESSAGE_ID_SENSOR_EVENT   "com.anyconnect.sensor.event";
  1. Call registerMessageCallback(std::string messageType, MessageCallback callback) method of Accessclass for both vision events and sensor events. messageType for vision events is MESSAGE_ID_VISION and for sensor events is MESSAGE_ID_SENSOR_EVENT.

Declaration of MessageCallback is:

typedef std::function<void(const MessageData& data)> MessageCallback;

and definition of MessageData is:

class MessageData
{
public:
    /// On incoming message, provides sender Id. On outgoing message should set recipient Id.
    Endpoint remoteId;
    std::string type; /// Message type
    std::string text; /// Message text
};
  1. Once the callback is registered, you will start receiving vision notifications of your Associated endpoints through this callback method
    AccessRet accessRet = access->registerMessageCallback([messageType UTF8String],
                                    [self](const MessageData &data) {
                // endpointId of the endpoint from where notification is sent
                Endpoint endpointId = data.remoteId;
                // defines notification type.
                // Compare with MESSAGE_ID_VISION or MESSAGE_ID_SENSOR_EVENT for getting the type
                std::string type = data.type;
                // Contains the notification text
                std::string notificationText = data.text;
        });

For each vision notification, endpointId, type and the notificationText are provided through MessageData.

  • For vision events, the notificationText is provided into Base64 format.
W3sidGltZXN0YW1wIjoiVHVlIEZlYiAwNCAwNTowNTozNCBVVEMgMjAyMCIsImVuZHBvaW50UmVwb3J0ZWRUaW1lIjoiMTU4MDc5MjczMCIsImltYWdlVXJsIjoiaHR0cHM6Ly9hY2NpbmQwZHMxLmJsb2IuY29yZS53aW5kb3dzLm5ldC92aXNpb25zbmFwcy8yODcyL3NuYXBzLzIwMjAtMDItMDQlMjAwNTowNTozNC4zNTg/c2lnXHUwMDNkb2Z0WWpMRnJMbDNkOGVCeGJseDE0ZHFoeURsUlglMkZ4VVVIN3NqQ3NNZnIwJTNEXHUwMDI2c3RcdTAwM2QyMDIwLTAyLTA0VDA1JTNBMDUlM0EzNlpcdTAwMjZzZVx1MDAzZDIwMjAtMDItMDVUMDUlM0EwNSUzQTM2Wlx1MDAyNnN2XHUwMDNkMjAxNS0xMi0xMVx1MDAyNnNwXHUwMDNkclx1MDAyNnNyXHUwMDNkYiIsImVuZHBvaW50SWQiOiIyODcyIiwiaWRlbnRpZmllZENhbmRpZGF0ZUxpc3QiOltdLCJmYWNlUmVjdGFuZ2xlTGlzdCI6W10sImltYWdlQW5hbHl0aWNzIjp7ImNhdGVnb3JpZXMiOlt7Im5hbWUiOiJpbmRvb3JfdmVudWUiLCJzY29yZSI6IjAuNzM0Mzc1In1dLCJ0YWdzIjpbeyJuYW1lIjoiaW5kb29yIiwiY29uZmlkZW5jZSI6IjAuOTk5NTcwNjA4MTM5MDM4MSJ9LHsibmFtZSI6ImNlaWxpbmciLCJjb25maWRlbmNlIjoiMC45OTM1NjQ4NDQxMzE0Njk3In0seyJuYW1lIjoiZmxvb3IiLCJjb25maWRlbmNlIjoiMC45OTAxNTg1NTc4OTE4NDU3In0seyJuYW1lIjoiY29tcHV0ZXIiLCJjb25maWRlbmNlIjoiMC45ODg4MDMyNjc0Nzg5NDI5In0seyJuYW1lIjoid2FsbCIsImNvbmZpZGVuY2UiOiIwLjk4Mjc4MTE3MTc5ODcwNiJ9LHsibmFtZSI6InJvb20iLCJjb25maWRlbmNlIjoiMC45NDQ1NTIxODMxNTEyNDUxIn0seyJuYW1lIjoiZGVzayIsImNvbmZpZGVuY2UiOiIwLjk0MTA5MDcwMzAxMDU1OTEifSx7Im5hbWUiOiJvZmZpY2UgYnVpbGRpbmciLCJjb25maWRlbmNlIjoiMC45MTQ5NTc1ODI5NTA1OTIifSx7Im5hbWUiOiJjaGFpciIsImNvbmZpZGVuY2UiOiIwLjg3NDQyNTk0NzY2NjE2ODIifSx7Im5hbWUiOiJjb21wdXRlciBtb25pdG9yIiwiY29uZmlkZW5jZSI6IjAuNzQ5OTczNDE2MzI4NDMwMiJ9LHsibmFtZSI6InRhYmxlIiwiY29uZmlkZW5jZSI6IjAuNzM0OTI5MjAzOTg3MTIxNiJ9LHsibmFtZSI6ImxhcHRvcCIsImNvbmZpZGVuY2UiOiIwLjYxMTM3Mzc4MjE1Nzg5OCJ9LHsibmFtZSI6InRlbGV2aXNpb24iLCJjb25maWRlbmNlIjoiMC41MzQzMjgyODE4Nzk0MjUifSx7Im5hbWUiOiJmdXJuaXR1cmUiLCJjb25maWRlbmNlIjoiMC40MDI2MDkwODAwNzYyMTc2NSJ9LHsibmFtZSI6ImFyZWEiLCJjb25maWRlbmNlIjoiMC4zNzc0NTk1NTU4NjQzMzQxIn1dLCJkZXNjcmlwdGlvbnMiOnsidGFncyI6WyJpbmRvb3IiLCJjZWlsaW5nIiwicm9vbSIsInRhYmxlIiwiY2hhaXIiLCJsaXZpbmciLCJraXRjaGVuIiwiZnVybml0dXJlIiwiYXJlYSIsIm9mZmljZSIsIm9wZW4iLCJjb21wdXRlciIsImZpbGxlZCIsIm1hbiIsImxhcmdlIiwiZGVzayIsIndoaXRlIiwidGVsZXZpc2lvbiIsIndvbWFuIiwiYmVkIiwic3RhbmRpbmciLCJwZW9wbGUiXSwiY2FwdGlvbnMiOlt7InRleHQiOiJhIHJvb20gZmlsbGVkIHdpdGggZnVybml0dXJlIGFuZCBhIHRhYmxlIiwiY29uZmlkZW5jZSI6IjAuODA1MjYyMzA0MDExNTQ1MiJ9XX0sInJlcXVlc3RJZCI6ImI1YWYyYmVmLWQ2ZDItNGI3MC1hNDU5LWJmYzZmNDFkYmI3ZiIsIm1ldGFkYXRhIjp7IndpZHRoIjo2NDAsImhlaWdodCI6NDgwLCJmb3JtYXQiOiJKcGVnIn0sImZhY2VzIjpbXSwib2JqZWN0cyI6W3sib2JqZWN0IjoidGVsZXZpc2lvbiIsImNvbmZpZGVuY2UiOiIwLjc0MiIsIm9ianJlY3RhbmdsZSI6eyJ4IjoyNTMsInkiOjk4LCJ3aWR0aCI6MTE1LCJoZWlnaHQiOjg2fX0seyJvYmplY3QiOiJwZXJzb24iLCJjb25maWRlbmNlIjoiMC42NjkiLCJvYmpyZWN0YW5nbGUiOnsieCI6OTAsInkiOjI0NSwid2lkdGgiOjEyNCwiaGVpZ2h0IjoxMzB9fV0sImJyYW5kcyI6W119fV0=

Decode this text to get the actual vision events. Decoding this text will provide you a json array of vision events of your camera.

[
    {
    "timestamp": "Tue Feb 04 05:05:34 UTC 2020",
    "endpointReportedTime": "1580792730",
    "imageUrl": "https://accind0ds1.blob.core.windows.net/visionsnaps/2872/snaps/2020-02-04%2005:05:34.358?sig=oftYjLFrLl3d8eBxblx14dqhyDlRX%2FxUUH7sjCsMfr0%3D&st=2020-02-04T05%3A05%3A36Z&se=2020-02-05T05%3A05%3A36Z&sv=2015-12-11&sp=r&sr=b",
    "endpointId": "2872",
    "identifiedCandidateList": [],
    "faceRectangleList": [],
    "imageAnalytics": {
        "categories": [
        {
            "name": "indoor_venue",
            "score": "0.734375"
        }
        ],
        "tags": [
        {
            "name": "indoor",
            "confidence": "0.9995706081390381"
        },
        {
            "name": "ceiling",
            "confidence": "0.9935648441314697"
        },
        {
            "name": "floor",
            "confidence": "0.9901585578918457"
        },
        {
            "name": "computer",
            "confidence": "0.9888032674789429"
        },
        {
            "name": "wall",
            "confidence": "0.982781171798706"
        },
        {
            "name": "room",
            "confidence": "0.9445521831512451"
        },
        {
            "name": "desk",
            "confidence": "0.9410907030105591"
        },
        {
            "name": "office building",
            "confidence": "0.914957582950592"
        },
        {
            "name": "chair",
            "confidence": "0.8744259476661682"
        },
        {
            "name": "computer monitor",
            "confidence": "0.7499734163284302"
        },
        {
            "name": "table",
            "confidence": "0.7349292039871216"
        },
        {
            "name": "laptop",
            "confidence": "0.611373782157898"
        },
        {
            "name": "television",
            "confidence": "0.534328281879425"
        },
        {
            "name": "furniture",
            "confidence": "0.40260908007621765"
        },
        {
            "name": "area",
            "confidence": "0.3774595558643341"
        }
        ],
        "descriptions": {
        "tags": [
            "indoor",
            "ceiling",
            "room",
            "table",
            "chair",
            "living",
            "kitchen",
            "furniture",
            "area",
            "office",
            "open",
            "computer",
            "filled",
            "man",
            "large",
            "desk",
            "white",
            "television",
            "woman",
            "bed",
            "standing",
            "people"
        ],
        "captions": [
            {
            "text": "a room filled with furniture and a table",
            "confidence": "0.8052623040115452"
            }
        ]
        },
        "requestId": "b5af2bef-d6d2-4b70-a459-bfc6f41dbb7f",
        "metadata": {
        "width": 640,
        "height": 480,
        "format": "Jpeg"
        },
        "faces": [],
        "objects": [
        {
            "object": "television",
            "confidence": "0.742",
            "objrectangle": {
            "x": 253,
            "y": 98,
            "width": 115,
            "height": 86
            }
        },
        {
            "object": "person",
            "confidence": "0.669",
            "objrectangle": {
            "x": 90,
            "y": 245,
            "width": 124,
            "height": 130
            }
        }
        ],
        "brands": []
    }
    }
]

Getting Vision Event Playback URL

To get playback video URL of vision events, make a HTTP GET request to the following URL.

https://api.anyconnect.com/media/recordings

The following parameters are required for making the request.

ParameterTypeDescription
endpointIdStringId of the endpoint where vision event has occurred.
secretTokenStringSecret token of the requesting user.
startingTimeLongStarting time / Endpoint reported time of the vision event in second.

The above request provides the recorded media URLs in the response. See the sample response below.

{
    "recordingUrl": "https://accind0ds1.blob.core.windows.net/recording/3129/000000001583808070_vid_1.mp4?sig=RlnqHl91Ks1jhs9WCYnjPFm5eX0jOYX0RmGA%2FrXPUlk%3D&st=2020-04-02T12%3A48%3A16Z&se=2020-04-03T12%3A48%3A16Z&sv=2015-12-11&sp=r&sr=b",
    "recordingUrls": [
    "https://accind0ds1.blob.core.windows.net/recording/3129/000000001583808070_vid_1.mp4?sig=RlnqHl91Ks1jhs9WCYnjPFm5eX0jOYX0RmGA%2FrXPUlk%3D&st=2020-04-02T12%3A48%3A16Z&se=2020-04-03T12%3A48%3A16Z&sv=2015-12-11&sp=r&sr=b"
    ],
    "seekPos": 0,
    "startTime": 1583808070,
    "endTime": 1583808070
}

You will find the playback URLs of events captured in multiple sources of your camera to the recordingUrls of the response.