Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 22 Next »

Overview

3VR Appliances and Enterprise Appliances support several APIs which can be accessed using web services. This has two key advantages for those writing client applications:

  1. These APIs can be used by client applications remotely across a network.

  2. Client applications can be written in almost any programming language.

3VR's Web Services APIs are based on standard protocols and formats such as HTTP, XML, REST, and SOAP which are supported in all major programming environments. In addition, the 3VR Web Services SDK contains sample code and support libraries for several popular programming languages.

In total, the 3VR Web Services API is comprised of 4 APIs:

  • The 3VR REST API gives client programs access to camera information, system settings, health monitoring data, video, images, and more with RESTful HTTP requests

  • The 3VR External System Activity API (SOAP) is used by client programs to add events to the 3VR system's database. These include bridges to Point of Sale (POS) systems, access control systems and transaction recording systems. The External System Activity API uses a Simple Object Access Protocol (SOAP) binding that lets client applications define event types and metadata types and inject individual events.

  • The 3VR External Query API lets client programs query for specific events in the set of events recorded by the 3VR system. 3VR provides RESTful access to some of the most common queries, but client programs can also send custom XML-based queries to return only events of interest. Regardless of which method is chosen, events are returned in XML format and use URLs to reference associated images and videos.

  • The 3VR Live Query API allows client programs to receive a continuous stream of new events matching an XML query. Clients can choose feeds based on the type of event or whether the event has a particular alert associated with it. The Live Query API uses the same XML predicate request as the External Query API, except the appliance will returns a continuous stream of events instead of a fixed set.

Application developers may use one API or a combination of APIs depending on their needs.

What does an Event mean?

3VR's "Searchable Surveillance" model is built around the creation of events. An event represents an action detected by the 3VR system, such as motion observed by a camera or the detection of a specific face. An event consists of two main components:

  • Event data: pieces of information such as the date, camera number, transaction ID, etc.

  • Event video: a video clip from the time when the event occurred.

Each event captured by the 3VR system is represented in OpCenter by an event card. Event cards are labeled with the type of event, the date and time the event card was created, and other information about the event.

The simplest event type is a Motion event. Motion events are created when the system detects movement in a camera's field of view. All motion event cards contain the following elements in storyboard view:

  • Images: each motion event card displays up to three still frames from the event:

  • Camera number and name: the number and name of the camera that captured the motion event.

  • Event start time: the time that motion was first detected by the camera.

  • Event duration: the length of time continuous motion was detected.

In addition to basic video recording, events can be generated by integration with external systems (e.g. transaction, access control, POS, etc.) and analytics plug-ins.

Choosing the Right API

Before embarking on a project using a 3VR API, application developers should carefully review each API's description and sample code to ensure they have selected the correct API(s) for their purposes. The following guidelines apply:

  • To create events on the 3VR appliance, use the 3VR External System Activity API

  • To request and obtain events from the 3VR Appliance that match certain criteria (date, camera, event type, etc.) use the 3VR External Query API.

  • To request and obtain a continuous stream of events matching a query, use the 3VR Live Query API.

  • To request information about a 3VR Enterprise Appliance, a single appliance, a camera, or to obtain video or images from a particular camera, use the 3VR REST API.

There are two approaches to developing with the 3VR API: you can either work with the API directly using libraries provided in your programming language of choice, or use 3VR's helper code provided for the language in which you are programming. Both approaches are supported, and the approach you choose will depend on your particular circumstances.

Even if you are writing directly to your language's interfaces, you may find it useful to review the helper code. The source code to the helper code is included in the SDK.

What’s in the SDK?

This manual is associated with a Software Development Kit that has useful tools for programming with 3VR Web services. These include specification files, such as XML schemas, WSDL files, library bindings, source code, and samples of real applications built using these APIs. Also included is a copy of the API documentation in PDF form.

Structure of the API Documentation

3VR's API documentation contains sections for each of the individual APIs. All users should read this Overview and the "Getting Started" section, and then proceed to the documentation for their API of choice.

All of the API-specific sections contain information on the format of the request to the appliance and what to expect in return.

The 3VR External System Activity API and the 3VR External Query API also include sample code to demonstrate the format of the XML request predicate. The 3VR External System Activity API currently includes examples in C# and Java. The 3VR External Query API has examples in Java and Python. Contact your 3VR representative if you are interested in writing client code in other languages.

The final section contains reference material on the structure of XML-formatting for use in specifying queries and processing the events returned from queries.

Getting Started

Enabling Web Services

A 3VR VIP Appliance or Enterprise Appliance must have web services enabled in order to accept incoming messages. Enable web services with the following steps:

  1. Launch 3VR System Manager.

  2. In the Configure panel of System Manager, right-click the name of the appliance and select Start Web Services.

  3. A pop up will appear indicating that web services is now running.

Enabling Demand Video Recording

If you plan to create events, set the Enable Demand Video Recording setting to Yes for each camera that will have generic events. This setting will buffer video so it is available for events even if there is not any current motion.

3VR REST API

The 3VR REST API gives client programs access to camera information, system settings, health monitoring data, video, images, and more with HTTP GET requests.

Authentication

The 3VR REST API uses HTTP Basic Authentication and validates against an appliance’s users. This requires an ’Authorization: Basic’ header in the request followed by a base64 encoded user name and password. This request header is case sensitive and must be passed with every request. The format for the user name and password is username:password. As an example, encoding ‘username:password’ to base64 results in ‘dXNlcm5hbWU6cGFzc3dvcmQ=’, and the request header would be the following:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

The server will also provide the challenge required for browser authentication. To test in a browser, navigate to a route and enter a valid user name and password in the dialog that’s displayed. The browser will then handle the authentication call.

All permissions, password constraints, authentication attempt limits, and inactivity limits for users are respected. If a user does not have access to an appliance, channel, view, etc. that information will not be returned in the response. When authentication fails the server will respond with a 401 HTTP status code and a JSON object in the body that includes the ‘AuthenticateResponse’ and a ‘Message’ describing the error. For example:

{ "AuthenticateResponse": "PasswordIncorrect", "Message": "Invalid user name or password" }

The following table lists the possible responses:

Port

The 3VR REST API runs on port 8080 and uses SSL, so the server can be accessed via:

https://hostaddress:8080

All exchanges are secured using HTTP BASIC authentication. The user names and passwords must match users that have been added to the 3VR system in System Manager.

Sample Request API

This sample displays the structure of a GET request to an appliance using the 3VR REST API.

In this example, we are requesting a list of system settings, but requests for different information may be made by modifying the path of the request URL (shown in bold text in the following example).

import urllib2, sys
def auth(hostname,username,password):
url = “https://%s:8080/” % (hostname)
password _ mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
handler = urllib2.HTTPBasicAuthHandler(password _ mgr)
opener = urllib2.build _ opener(handler)
urllib2.install _ opener(opener)
password _ mgr.add _ password(None, url, username, password)
def get _ settings(hostname):
url = "https://%s:8080/settings" % (hostname) #url path to request settings
try:
req = urllib2.urlopen(url)
return req.read()
except urllib2.HTTPError, e:
print "HTTP error: %s" % e.code
except Exception, e:
print e
return ""
if _ _ name _ _ == "_ _ main _ _":
try:
hostname = sys.argv[1]
except:
print "usage: settingsAPI.py [IP address or hostname]"
sys.exit(1)
auth(hostname,"techrep","3MeDeee")
settingsxml = get _ settings(hostname)

Headers and Responses

The information below will apply to most 3VR REST API routes. 3VR is in the process of unifying and normalizing its API, so the 3VR REST API routes marked with an asterisk (*) are those still in need of updating. For now, their response will be in XML and they will not take the 'Accept' request header, but will do so in the future.

The default response of all routes will be formatted as JSON objects except for the channel image and video routes.; images routes will return an image, see the routes below for more details. The ‘Accept’ request header allows specifying the desired content type to be returned. For example:

Accept: application/xml
Accept: application/json

Please note most browsers will include application/xml in the request header by default, so for debugging purposes an accept argument in the query string may be required to request a JSON formatted response. For example, when retrieving the list of appliances in JSON format using a browser, access the following URL:

https://hostaddress:8080/appliances?accept=application/json

3VR REST API Routes

/appliances

https://[IP address or hostname]:[port]/appliances

Options

?regions=true if included, the returned list of appliances will be arranged in regions

Sample XML Response

<ArrayOfApplianceInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ApplianceInfo>
<Id>1</Id>
<Name>3VR Enterprise Appliance</Name>
<Address>10.100.2.22</Address>
<MachineType>EnterpriseServer</MachineType>
<TimeZoneKey>Pacific Standard Time</TimeZoneKey>
<TimeZoneOffset>480</TimeZoneOffset>
<Created>0001-01-01T00:00:00</Created>
<Updated>2012-07-26T00:42:04</Updated>
<VideoStart>0001-01-01T00:00:00</VideoStart>
<SyncDate>2012-07-02T11:00:14</SyncDate>
<ObjectType>appliance</ObjectType>
</ApplianceInfo>
<ApplianceInfo>
<Id>2</Id>
<Name>Lake Merritt Branch</Name>
<Address>10.100.2.202</Address>
<MachineType>Integrated</MachineType>
<TimeZoneKey>Pacific Standard Time</TimeZoneKey>
<TimeZoneOffset>480</TimeZoneOffset>
<Created>2011-04-26T18:37:30</Created>
<Updated>2012-07-27T08:56:51</Updated>
<VideoStart>2011-04-26T18:46:35</VideoStart>
<SyncDate>2012-07-27T08:56:51</SyncDate>
<ObjectType>appliance</ObjectType>
</ApplianceInfo>
</ArrayOfApplianceInfo>

Sample JSON Response

[
{
Id: 1,
Name: "3VR Enterprise Appliance",
Address: "10.100.2.22",
MachineType: "EnterpriseServer",
TimeZoneKey: "Pacific Standard Time",
TimeZoneOffset: 480,
Created: "/Date(-62135568000000)/",
Updated: "/Date(1343549702000)/",
VideoStart: "/Date(-62135568000000)/",
SyncDate: "/Date(1341252014000)/",
ObjectType: "appliance"
},
{
Id: 2,
Name: "Lake Merritt Branch",
Address: "10.100.2.202",
MachineType: "Integrated",
TimeZoneKey: "Pacific Standard Time",
TimeZoneOffset: 480,
Created: "/Date(1303868250000)/",
Updated: "/Date(1343673311000)/",
VideoStart: "/Date(1303868795000)/",
SyncDate: "/Date(1343673311000)/",
ObjectType: "appliance"
}
]

/health

https://[IP address or hostname]:[port]/health

Sample XML Response

<?xml version="1.0" ?>
<ArrayOfHealthAlertInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<HealthAlertInfo>
<DisplayLabel>Camera or Camera Connection Failure</DisplayLabel>
<Id>3</Id>
<StartTime>2012-06-20T11:24:10</StartTime>
<EndTime>2012-07-27T04:03:55</EndTime>
<Message>Camera '1. Shipping Room' is not sending video.</Message>
</HealthAlertInfo>
</ArrayOfHealthAlertInfo>

/enterprisehealth

https://[IP address or hostname]:[port]/enterprisehealth

Sample XML Response

<ArrayOfEnterpriseHealthAlertInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EnterpriseHealthAlertInfo>
<ApplianceId>2</ApplianceId>
<ApplianceName>Lake Merritt Branch</ApplianceName>
<ApplianceAddress>10.100.2.202</ApplianceAddress>
<DisplayLabel>Camera or Camera Connection Failure</DisplayLabel>
<Id>6</Id>
<StartTime>2012-06-11T22:32:45</StartTime>
<EndTime>2012-07-27T15:03:55</EndTime>
<TriggerTime>2012-06-11T23:32:45</TriggerTime>
<Message>Camera '7. Mercado' is not sending video.</Message>
</EnterpriseHealthAlertInfo>
<EnterpriseHealthAlertInfo>
<ApplianceId>2</ApplianceId>
<ApplianceName>Lake Merritt Branch</ApplianceName>
<ApplianceAddress>10.100.2.202</ApplianceAddress>
<DisplayLabel>Camera or Camera Connection Failure</DisplayLabel>
<Id>7</Id>
<StartTime>2012-06-11T22:32:45</StartTime>
<EndTime>2012-07-27T15:03:55</EndTime>
<TriggerTime>2012-06-11T23:32:45</TriggerTime>
<Message>Camera '6. Caja' is not sending video.</Message>
</EnterpriseHealthAlertInfo>
</ArrayOfEnterpriseHealthAlertInfo>

/appliancemetadata*

https://[IP address or hostname]:[port]/appliancemetadata

Sample XML Response

Sample Response XML
<InfoCollectionOfMetadataInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Infos>
<MetadataInfo>
<Guid>d4fd02e5-d035-4d7e-9aa4-2535a561a748</Guid>
<Name>Custom Text Field</Name>
<Value>Test Value</Value>
</MetadataInfo>
<MetadataInfo>
<Guid>d4fd02e5-d035-4d7e-9aa4-2535a561a748</Guid>
<Name>Custom Number Field</Name>
<Value>12</Value>
</MetadataInfo>
</Infos>
</InfoCollectionOfMetadataInfo>

/settings*

https://[IP address or hostname]:[port]/settings

Sample XML Response

<InfoCollectionOfSettingDefinitionInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Infos>
<SettingDefinitionInfo>
<Id>1</Id>
<Name>AdminEMail</Name>
<Category>Email</Category>
<ChannelId>0</ChannelId>
</SettingDefinitionInfo>
<SettingDefinitionInfo>
<Id>2</Id>
<Name>AllowLocalCaseManagement</Name>
<Category>General</Category>
<ChannelId>0</ChannelId>
</SettingDefinitionInfo>
<SettingDefinitionInfo>
<Id>3</Id>
<Name>BackupMedia</Name>
<Category>General</Category>
<ChannelId>0</ChannelId>
</SettingDefinitionInfo>
</SettingDefinitionInfo>
...
</Infos>
</InfoCollectionOfSettingDefinitionInfo>

/settingvalue*

https://[IP address or hostname]:[port]/settingvalue

Sample XML Response

<InfoCollectionOfSettingValueInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Infos>
<SettingValueInfo>
<Id>20</Id>
<Value>false</Value>
<ComponentId>5</ComponentId>
</SettingValueInfo>
</Infos>
</InfoCollectionOfSettingValueInfo>

/channelinfo*

https://[IP address or hostname]:[port]/channelinfo

<InfoCollectionOfChannelInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Infos>
<ChannelInfo>
<Name>Street View</Name>
<Number>4</Number>
<Id>19</Id>
<ChannelDriverName>GenericIPCameraDriver</ChannelDriverName>
<PtzState>2</PtzState>
<IsActive>false</IsActive>
<ChannelType>3</ChannelType>
</ChannelInfo>
<ChannelInfo>
<Name>Classroom</Name>
<Number>5</Number>
<Id>20</Id>
<ChannelDriverName>GenericIPCameraDriver</ChannelDriverName>
<PtzState>2</PtzState>
<IsActive>false</IsActive>
<ChannelType>3</ChannelType>
</ChannelInfo>
...
</Infos>
</InfoCollectionOfChannelInfo>

/hosts

https://[IP address or hostname]:[port]/hosts

Sample XML Response

<ArrayOfHostsInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.
w3.org/2001/XMLSchema">
<HostsInfo>
<Label>Lake Merritt Branch</Label>
<Id>2</Id>
</HostsInfo>
<HostsInfo>
<Label>Mission District Branch</Label>
<Id>3</Id>
</HostsInfo>
</ArrayOfHostsInfo>

/person/*

https://[IP address or hostname]:[port]/person/

Sample XML Response

<?xml version="1.0" encoding="utf-8"?> <ThreeVRDbSync version="7.0" sourceSystem="">
<Persons>
<Person primarykey="Id">
<simplefield name="Id" value="1"/>
<simplefield name="FirstName" value="John"/>
<simplefield name="LastName" value="Smith"/>
<simplefield name="LastSeen" value="2013-03-02T21:22:32-05:00"/>
<simplefield name="FirstSeen" value="2013-03-02T21:22:32-05:00"/>
<simplefield name="UseForAutoMatch" value="false"/>
<complexfield name="Group">
<values>
<value>
<simplefield name="objectName" value="Imported People"/>
<simplefield name="Description" value="Imported People"/>
<simplefield name="AutoMatchType" value="UsePersonAutoMatchSetting"/>
</value>
</values>
</complexfield>
<image format="jpeg" width="303" height="300">
[IMAGE DATA]
</image>
</Person>
<Person primarykey="Id">
<simplefield name="Id" value="2"/>
<simplefield name="FirstName" value="Julie"/>
<simplefield name="LastName" value="Smith"/>
<simplefield name="LastSeen" value="2013-03-02T21:22:33-05:00"/>
<simplefield name="FirstSeen" value="2013-03-02T21:22:33-05:00"/>
<simplefield name="UseForAutoMatch" value="false"/>
<complexfield name="Group">
<values>
<value>
<simplefield name="objectName" value="Employees"/>
<simplefield name="Description" value="Employees"/>
<simplefield name="AutoMatchType" value="UsePersonAutoMatchSetting"/>
</value>
</values>
</complexfield>
<simplefield name="Employee ID" value="80"/>
<simplefield name="Employee Type" value="Full Time"/>
<simplefield name="Gender" value="Female"/>
<simplefield name="Hair Color" value="Black"/>
<image format="jpeg" width="280" height="280">
[IMAGE DATA]
</image>
</Person>
</Persons>
</ThreeVRDbSync>

/livevideo

https://[IP address or hostname]:[port]/livevideo

Sample Response

/video

https://[IP address or hostname]:[port]/video/

WILL BE DEPRECATED IN NEXT RELEASE, USE /channels

Returns stored video from the camera with the given camera number and options (start time, end time, length, framerate, and/or resolution). Note: Datetime values are formatted according to the ISO 8601 specification: YYYY-MM-DDTHH:MM:SS For example, 2012-12-05T13:40:27. For more information, see this article from the W3C W3.org: Date and Time Formats.

/event*

https://[IP address or hostname]:[port]/event/

Sample Response

/liveimage

https://[IP address or hostname]:[port]/liveimage/

Sample Response

/channels

https://[IP address or hostname]:[port]/channel

/time

https://[IP address or hostname]:[port]/time

/version

https://[IP address or hostname]:[port]/version

/views

https://[IP address or hostname]:[port]/views

Input for POST/views

{
"Id":null,
"Name":"1 Channel",
"Shared":false,
"UserName":"user",
"UserId":null,
"Channels":[
{
"Id":9,
"Name":"Camera 9",
"ChannelDrive":null,
"IsActive":true,
"ChannelType":"IPNetworkCamera",
"ThumbnailUrl":null,
"LocalId":0,
"Appliance":{
"Id":1,
"Name":"Developer Workstation",
"Address":null,
"MachineType":"Integrated",
"TimeZoneKey":"Pacific Standard Time",
"TimeZoneOffset":480,
"Created":"/Date(1351818098000)/",
"Updated":"/Date(1353442448000)/",
"VideoStart":"/Date(1352497452000)/",
"SyncDate":"/Date(1351818098000)/"
},
"selected":false,
"isEnterprised":false,
"Number":9,
"ChannelDriver":"GenericIPCameraDriver",
"ImageUrl":"https:///channels/9/image",
"hostname":""
}
],
}

Input for PUT/views

{
"Id":15,
"Name":"Single Channel View",
"Shared":false,
"UserName":"techrep",
"UserId":2,
"Channels":[
{
"Id":9,
"Name":"Camera 9",
"ChannelDrive":null,
"IsActive":true,
"ChannelType":"IPNetworkCamera",
"ThumbnailUrl":null,
"LocalId":0,
"Appliance":{
"Id":1,
"Name":"Developer Workstation",
"Address":null,
"MachineType":"Integrated",
"TimeZoneKey":"Pacific Standard Time",
"TimeZoneOffset":480,
"Created":"/Date(1351818098000)/",
"Updated":"/Date(1353442448000)/",
"VideoStart":"/Date(1352497452000)/",
"SyncDate":"/Date(1351818098000)/"
},
"selected":false,
"isEnterprised":false,
"Number":9,
"ChannelDriver":"GenericIPCameraDriver",
"ImageUrl":"https:///channels/9/image",
"hostname":""
}
],
}

/rtsp

https://[IP address or hostname]:[port]/rtsp

Sample XML Response

<RestRTSPResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Message>OK</Message>
<Uri>rtsp://10.10.10.10:554/Stream3</Uri>
</RestRTSPResponse>

Sample JSON Response

{
"Message": "OK",
"Uri": "rtsp:\/\/10.10.10.10:554\/Stream3"
}

The RTSP URI will always contain the local network IP address. If there are plans to expose the 3VR system to an external network via NAT, then its possible to specify a special file to replace the RTSP IP with the external address. Please contact 3VR Technical Support for assistance with setting up the file to replace the RTSP IP Address.

If an RTSP client issues a TEARDOWN command, the API user must request the RTSP URL again to begin video streaming.

3VR Technical Support Contact Information
Additionally, If you are having trouble with a 3VR system or application, contact 3VR Technical Support by phone at 415-513-4572 or email support@3VR.com Monday through Friday, 5 a.m. to 6 p.m. Pacific Time (8 a.m. to 9 p.m. Eastern Time) for assistance.

3VR External System Activity API - SOAP

Overivew

The 3VR External System Activity API allows third parties to define their own event types for the 3VR system and add instances of these events to the 3VR system. These events can then be displayed and searched for using 3VR's OpCenter application. In OpCenter, these events can be correlated with other event types using the "Search for related events" option in the Search panel.

The 3VR External System Activity API is built on the Simple Object Access Protocol (SOAP) using HTTP, a standard web services protocol accessible from a wide variety of platforms and languages. Since SOAP is based on XML, it is easy to build requests and process replies.

To support custom events, 3VR has a framework called generic events. These events are similar to internally defined events, but their structure can be defined by external agents. A given 3VR system can have an arbitrary number of defined generic event types. However, for usability reasons, we recommend that a given vendor use a single event type and differentiate using metadata. However, this is not a hard rule. Generic events will be displayed alongside the other event types, such as Motion and Face, in the Monitor, Search, and Cases panels of OpCenter.

Generic events appear in the software using individually defined names, displayed on each generic event card. When the user chooses to view smaller event cards, the short name is displayed. For example, in the event card below, the generic event name is "Bank Teller"

Generic events can integrate custom field data. The API name for a custom field is a metadata field. The generic event definition specifies the event type name, short name, help text, metadata fields, and a globally unique identifier (GUID). The generic event definition GUID identifies the generic event type and metadata fields across different 3VR servers.

Each metadata field has name, description, type, display position, display format and GUID.

  • Name appears in the event details and may appear on the event card depending on the display format.

  • Type specifies the kind of data stored in the field. The type can be String, Number, DateTime, or EnumeratedType.

  • Description is a text string that describes the field.

  • Display position controls the order in which the metadata fields are displayed.

  • Display format controls the way the data is displayed on the large event cards.

When you define a new generic event type, you will have to create GUIDs for the event type itself and each of the metadata fields that you are defining. It is important to use the same GUIDs for every server on which you use your application. GUIDs can be generated in a number of ways.

  • At the time of this writing, GUIDs could be generated on the following sites:

  • Microsoft Visual Studio includes a GUID generating tool called GUIDGen.exe. This program is located in \Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Binin Visual Studio 2010.

  • When the generic event definition is created, if a GUID has not been specified, a GUID will be generated automatically and returned in the response. Incorporate the response GUID into your code whenever you create the definition.

3VR is not affiliated with these sites in any way; an Internet search for "GUID generator" can provide additional resources.

A typical application of the External System Activity API will:

  1. Authenticate the user of the application. The user needs to be defined in 3VR System Manager. The authenticate call returns an authentication token that is used in SOAP Header for all subsequent requests.

  2. Create the generic event definition if it does not already exist.

  3. Based on some external stimulus, create a generic event associated with a camera.

Authentication is accomplished using the IAuthenticateService. The IGenericEventService provides the rest of the API.

Browsing 3VR External System Activity API Services

Verify that the Web Services is running by pointing a browser at any of the following 3VR External System Activity API services

Click on any of the asmx links to see the available services. The SOAP WSDL is available at the Service Description link. The service call XML specification is available on the operation link.

Authentication

Authenticate against the 3VR users. The Soap Header can be blank. It will return the Token for use in the SOAP header for subsequent operations.

Create Events

Once authenticated you are ready to create events with the IGenericEventService. The WSDL is available by clicking the Service Description link.

https://hostaddress:8080/3vr/IGenericEventService.asmx:

The primary operations are:

  • CreateGenericEventDefinition: Create a Generic Event Definition for new generic events. Values for Type = String, Number, DateTime, or EnumeratedType

  • CreateGenericEvent: Create a Generic Event from the server.

The other operations are used in support of generic event creation.

  • Channels: Get a list of channels.

  • CustomFieldNames: Get a list of Custom Field Names associated with a person profile in the 3VR system. Used for FaceComparison events.

  • DeleteGenericEvent: Delete a Generic Event.

  • DeleteGenericEventDefinition: Delete a Generic Event Definition.

  • GenericEvent: Get a Generic Event from the server.

  • GenericEventDefinitionByGUID: Find an the Generic Event Definitions with the specified GUID.

  • GenericEventDefinitionsAll: Get all Generic Event Definitions.

  • GenericEventDefinitionsByName: Find all the Generic Event Definitions with the provided name.

  • UpdateGenericEvent: Update a Generic Event.

  • UpdateGenericEventDefinition: Update an existing Generic Event Definition GUIDs must match for existing elements

Developing Client Programs

3VR Web Services are design to work in various environments (.NET, Java, Python, etc.).

.NET

If you are working in .NET, the program wsdl.exe (in \Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin) will automatically generate client code. For example, to generate C#, run the following at the command line:

> wsdl /language:CS https://[IP or host name of 3VR appliance]:8080/3vr/IGenericEventService.asmx?WSDL

and WSDL.exe will generate client code to access Generic Event operations.

Java XML

For Java systems, 3VR provides an example using Apache.org's Axis package and WSDL2Java to generate the client code using JAX-RPC and JAWS API's. This sample uses Axis 1.4 from Apache.org and JAF activation.jar and mail.jar from java.sun.com

  1. Set AXIS _ HOME to where you installed Axis, e.g. C:\java\axis-1 _ 4\lib.

  2. Set up or copy the log4j properties from AXIS _ HOME, and set up AXIS _ HOME in the environment.

  3. The CLASSPATH will look something like:

    CLASSPATH = .;%AXIS _ HOME%\axis.jar;%AXIS _ HOME%\commons-discovery-0.2.jar;%AXIS _ HOME%\commons-
    logging-1.0.4.jar;%AXIS _ HOME%\jaxrpc.jar;%AXIS _ HOME%\log4j-1.2.8.jar;%AXIS _ HOME%\saaj.
    jar;%AXIS _ HOME%\wsdl4j-1.5.1.jar;%AXIS _ HOME%\mail.jar;%AXIS _ HOME%\activation.jar

  4. Run WSDL2Java at the command line to create the client library.

    > java org.apache.axis.wsdl.WSDL2Java --output src --package com. _ 3vr.Services http://
    localhost/3vr/IAuthenticateService.asmx?WSDL>java org.apache.axis.wsdl.WSDL2Java --output
    src --package com. _ 3vr.Services http://localhost/3vr/IGenericEventService.asmx?WSDL
  5. With the generated code, use of the Authenticate operation in Java becomes:

    try{
    IAuthenticateServiceLocator locator = new IAuthenticateServiceLocator();
    java.net.URL url = new java.net.URL(serverUrl + "IAuthenticateService.asmx");
    IAuthenticateServiceSoap _ PortType port = locator.getIAuthenticateServiceSoap(url);
    AuthenticateToken token = port.authenticate("user", "password");
    System.out.println("Status " + token.getStatus() + "Token " + token.getToken());
    if(token.getStatus().equals("Success"))
    {
    return token.getToken();
    }
    }
    catch(Exception e)
    { System.out.println(e.getMessage());
    
    
  6. To use the generic operations, the token needs to be set in the header. The SoapHeaderInfo class 3VR uses to put the Service Token in the SoapHeader is not created by WSDL2Java. We created one to match the other classes generated. Putting the Service token in the SoapHeader becomes:

import javax.xml.namespace.QName;
import org.apache.axis.message.SOAPHeaderElement;
try
{
IGenericEventServiceLocator locator = new IGenericEventServiceLocator();
java.net.URL url = new java.net.URL(serverUrl + "IGenericEventService.asmx");
genericEventService = locator.getIGenericEventServiceSoap(url);
QName qname = new QName("http://3vr.com", "SoapHeaderInfo");
SoapHeaderInfo SoapHeaderInfo = new SoapHeaderInfo("", token);
SOAPHeaderElement header = new SOAPHeaderElement(qname, SoapHeaderInfo);
org.apache.axis.client.Stub stub = (org.apache.axis.client.Stub)genericEventService;
stub.setHeader(header);
}c
atch(Exception e)
{
System.out.println(e.getMessage());
}

For more details, see the source for the BankTeller Java sample.

Sending Request XML

The SOAP Envelope wraps the request, and the <soap:body>contains the details of the request. Here are examples of the XML for Authenticate. In following example we will usually display the XML for the body and omit the header and wrapping XML.

SOAP 1.1 Request Envelope

POST /3vr/IAuthenticateService.asmx HTTP/1.1
Host: 10.100.1.105
Port: 8080
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://3vr.com/Authenticate"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<SoapHeaderInfo xmlns="http://3vr.com">
<Address>string</Address>
<ServiceToken>string</ServiceToken>
</SoapHeaderInfo>
</soap:Header>
<soap:Body>
<Authenticate xmlns="http://3vr.com">
<username>string</username>
<password>string</password>
</Authenticate>
</soap:Body>
</soap:Envelope>

SOAP 1.1 Response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<AuthenticateResponse xmlns="http://3vr.com">
<AuthenticateResult>
<Token>string</Token>
<Status>string</Status>
</AuthenticateResult>
</AuthenticateResponse>
</soap:Body>
</soap:Envelope>

SOAP 1.2 Request Envelope

POST /3vr/IAuthenticateService.asmx HTTP/1.1
Host: 10.100.1.105
Port: 8080
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<SoapHeaderInfo xmlns="http://3vr.com">
<Address>string</Address>
<ServiceToken>string</ServiceToken>
</SoapHeaderInfo>
</soap12:Header>
<soap12:Body>
<Authenticate xmlns="http://3vr.com">
<username>string</username>
<password>string</password>
</Authenticate>
</soap12:Body>
</soap12:Envelope>

SOAP 1.2 Response

HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<AuthenticateResponse xmlns="http://3vr.com">
<AuthenticateResult>
<Token>string</Token>
<Status>string</Status>
</AuthenticateResult>
</AuthenticateResponse>
</soap12:Body>
</soap12:Envelope>

Authenticate

As shown in the examples above, the Authenticate operation sends the user name and password and receives a <Token> and <Status> in the response:

<AuthenticateResult>
<Token>string</Token>
<Status>string</Status>
</AuthenticateResult>

If all goes well the <Status> will contain "Success". The <Token> is used on the following request in the soap:Header<ServiceToken>.

CreateGenericEventDefinition

Generic event definitions control how events are displayed in OpCenter. The name and metadata fields are displayed on the event card, and metadata is displayed in event details. Users can search for events using metadata fields in the Search panel.

The metadata fields define custom data fields for the generic event. The GUID identifies the generic event and metadata fields across different 3VR servers. The GUID is instrumental when identifying the generic event and editing the generic event definition.

Each metadata field has a Name, Description, Type, Display Position, Display Format and GUID elements:

Generic Event Definition Metadata Fields

<Name> Appears in the event details and may appear on the event card, depending on the Display Format.
<Type> Defines the data type. Values include "String", "Number", "DateTime", or "EnumeratedType".

<Description> Describes the field.
<DisplayPosition> Sets the order the Metadata Fields are displayed. Valid display values are 0-100. Values over 100 are not displayed.
<DisplayFormat> Controls the way the data is displayed on large event cards. Allows simple formatting (bolding, joining lines and inserting new lines). See the following code sample for more information.
<EnumeratedData> Lists the valid data values for an EnumeratedType.

<CreateGenericEventDefinition xmlns="http://3vr.com">
<eventDefinition>
<Name>string</Name>
<ShortName>string</ShortName>
<GUID>string</GUID>
<HelpText>string</HelpText>
<MetadataFields>
<MetadataField>
<GUID>string</GUID>
<Name>string</Name>
<Description>string</Description>
<Type>String or Number or DateTime or EnumeratedType</Type>
<DisplayPosition>int</DisplayPosition>
<DisplayFormat>string</DisplayFormat>
<EnumeratedData xsi:nil="true" />
</MetadataField>
<MetadataField>
...
</MetadataField>
</MetadataFields>
</eventDefinition>
</CreateGenericEventDefinition>

Note: The ellipsis (…) means tags repeated from the previous block have been omitted.

Here is an example of a simple CreateGenericEventDefinition named "Example Event":

<CreateGenericEventDefinition xmlns="http://3vr.com">
<eventDefinition>
<Name>Example Event</Name>
<ShortName>Example</ShortName>
<GUID>66B886FA-F097-4290-89DD-E308E5E05A5</GUID>
<HelpText>Some help text that describes an Example Event.</HelpText>
<MetadataFields>
<MetadataField>
<GUID>1FE84583-F770-4b89-AE2B-FD247C90785</GUID>
<Name>Data</Name>
<Description>Data for the example</Description>
<Type>String</Type>
<DisplayPosition>1</DisplayPosition>
<DisplayFormat>{name} {value}</DisplayFormat>
</MetadataField>
</MetadataFields>
</eventDefinition>
</CreateGenericEventDefinition>

If we were to generate a generic event with this definition on a 3VR Appliance, "Example Event" would appear as an option in the event selector in OpCenter's Monitor and Search panels.

Furthermore, since Example Event has a metadata item with the <name> "Data" that is of <type> "string", users could create a search that would return only Example Events with a "Data" value matching their search string.

Generic Event Definition DisplayFormat

There are seven tags that can be used to format the text displayed for a generic event data field: {name}, {value}, {bold}, {newline}, {oneline}, {joinline}, and {wrap}. All other text inserted into the display format will be displayed as plain text.

To display a field with the name “Amount” and the value “$100” as “Amount: $100”, then, would require the following display format: Format: {name}: {value}

Result: Amount: $100

Making a portion of the text field bold requires putting a {bold} tag at the beginning and end of that section of text. There can only be two{bold} tags, and the first must be at the beginning of the display format. Displaying “Amount: $100” would require the following display format: {bold}{name}:{bold} {value}

The {newline} tag inserts a newline character into the text. The display format {name}:{newline}{value} will result in

Amount: $100

Conversely, the {oneline} tag removes all newline characters from the name and value strings not explicitly defined by a {newline} tag, replacing them with a single space.

The {joinline} tag can be used to put two or more fields on a single line. Placing {joinline} in a field’s display format will cause the next field to be displayed on the same line, to the right of the current field. For two fields, one describing gender and the other eye color, to be displayed as “Gender: Male Eye Color: Brown”, both fields can be given the following display format: {name}: {value} {joinline}. An arbitrary number of fields can be placed on the same line, limited only by screen space.

By default, OpCenter will display as much of each line as possible, and truncate any text that does not fit in the available space. If you do not wish to truncate text, use the {wrap} tag to wrap over-sized strings in a given field onto multiple lines. This tag cannot be used in conjunction with the {joinline} tag. Putting it all together, the Bank Teller event card shown here:

Putting it all together, the Bank Teller event card shown here:

Was created with the following generic event definition:

<CreateGenericEventDefinition xmlns="http://3vr.com">
<eventDefinition>
<Name>Bank Teller</Name>
<ShortName>Bank</ShortName>
<GUID>1cdf7bb4-2955-4716-b971-58daf7e73365</GUID>
<HelpText>Bank Teller Transactions</HelpText>
<MetadataFields>
<MetadataField>
<GUID>6e4a0f9d-38e9-4350-ab20-fa2cfa0729b3</GUID>
<Name>Account Type</Name>
<Description>Bank Account Type</Description>
<Type>String</Type>
<DisplayPosition>1</DisplayPosition>
<DisplayFormat>{bold}{value}{bold} {joinline}</DisplayFormat>
</MetadataField>
<MetadataField>
<GUID>21b35e5b-6098-4c91-a3c6-d4666af6a2d0</GUID>
<Name>Transaction Type</Name>
<Description>Bank Transaction Type</Description>
<Type>String</Type>
<DisplayPosition>2</DisplayPosition>
<DisplayFormat>{value}</DisplayFormat>
</MetadataField>
<MetadataField>
<GUID>5ef29aa5-3f87-461b-ba8a-dd1ed8f503f8</GUID>
<Name>Account Number</Name>
<Description>Bank Account</Description>
<Type>String</Type>
<DisplayPosition>3</DisplayPosition>
<DisplayFormat>{bold}Acct #{bold} {value}</DisplayFormat>
</MetadataField>
<MetadataField>
<GUID>ef6c4d44-7692-4127-9883-3ec390df46de</GUID>
<Name>Amount</Name>
<Description>Bank Transaction Amount</Description>
<Type>String</Type>
<DisplayPosition>4</DisplayPosition>
<DisplayFormat>{bold}Amt{bold} {value}</DisplayFormat>
</MetadataField>
<MetadataField>
<GUID>7da3178d-135f-4aad-91a4-eca544a781a2</GUID>
<Name>Teller Id #</Name>
<Description>Bank Teller Id</Description>
<Type>String</Type>
<DisplayPosition>5</DisplayPosition>
<DisplayFormat>{bold}Teller#{bold} {value}</DisplayFormat>
</MetadataField>
</MetadataFields>
</eventDefinition>
</CreateGenericEventDefinition>

The Details tab of the event editor will show all of the metadata fields and their values, and the Search panel makes these fields available for searching:

CreateGenericEvent

Once an event definition has been created, use CreateGenericEvent to send all the data for a new event:

<CreateGenericEvent xmlns="http://3vr.com">
<genericEvent>
<GUID>string</GUID>
<EventTime>dateTime</EventTime>
<StartTimeDelta>int</StartTimeDelta>
<EndTimeDelta>int</EndTimeDelta>
<UseServerTime>boolean</UseServerTime>
<ChannelId>long</ChannelId>
<DefinitionGUID>string</DefinitionGUID>
<CloseEvent>boolean</CloseEvent>
<MetadataList>
<GenericEventMetadata>
<GUID>string</GUID>
<Value>string</Value>
</GenericEventMetadata>
<GenericEventMetadata>
...
</GenericEventMetadata>
</MetadataList>
<Images/>
<SpecialSearchDataList/>
<FaceComparison/>
</genericEvent>
</CreateGenericEvent>

Generic Event Metadata Fields

  • <GUID> The GUID of the event; left empty for the Create operation

  • <EventTime> The DateTime of the event

  • <StartTimeDelta> Millisecond time span added to Event Time for the start of the Event Video. To start recording the video 2 seconds before the event time, the value would be -2000

  • <EndTimeDelta> Millisecond time span added to Event Time for the end of the Event Video. To stop recording the video 2 seconds after the event time, the value would be 2000.

  • <UseServerTime> Set to "true," the event time provided will be replaced with the server time when the event is recorded on the server. (The Event Time must still be set on the request. DateTime values cannot be null.)

  • <ChannelId> The ID of the camera recording the event.

  • <DefinitionGUID> The GUID of the Generic Event Definition.

  • <CloseEvent> If true the event is closed immediately, even if the event will update. It allows the details of the event to be available as soon as the event is created. There may be a delay while the video is buffered and saved.

  • <MetadataList> List of GUID, value pairs for the event.

  • <Images> Optional, supply images that can be inserted into the event. These images are used instead of images captured by the 3VR appliance. See "The Images Element" below for more information.

  • <SpecialSearchDataList> Internal use.

  • <FaceComparison> Optional, compares a reference person to a face event near the time the event is created.

CreateGenericEvent Response

The response to a succesful CreateGenericEvent request will contain the GUID of the Generic Event:

<CreateGenericEventResponse xmlns="http://3vr.com">
<CreateGenericEventResult>string</CreateGenericEventResult>
</CreateGenericEventResponse>

The Images Element

If the images for the event are provided from outside the 3VR appliance, use the <Images> tag. These images will be displayed in the event details.

<Images>
<GenericEventImage>
<Width>int</Width>
<Height>int</Height>
<Format>Unknown or Yuv444 or Yuv420 or Grayscale or GrayscaleRgb or Rgb or Jpeg or
Bitmap</Format>
<NominalAspectRatio>unsignedInt</NominalAspectRatio>
<AspectRatioAdjustment>double</AspectRatioAdjustment>
<ImageBuffer>base64Binary</ImageBuffer>
<ImageTime>dateTime</ImageTime>
</GenericEventImage>
<GenericEventImage>
...
</GenericEventImage>
</Images>

Each image sent with a generic event should have the following properties:

Generic Event Image Element Content

  • <Width> The pixel width of the image.

  • <Height> The pixel height of the image

  • <Format> The format of the Image Buffer bytes.

  • <NominalAspectRatio> Set to 2 for an NTSC interlaced image field and set to 1 for a mega pixel or non-interlaced image.

  • <AspectRatioAdjustment> Accounts for non-square pixels. Value is 1.0 for square pixels.

  • <ImageBuffer> Contains the base 64 encoded bytes of the image in the format specified in the <Format> tag.

  • <ImageTime> The DateTime of the image.

The SpecialSearchDataList Element

Leave the following eleemnt empty; it is reserved for internal use.

<SpecialSearchDataList>
<GenericEventSpecialSearchData>
<SearchEngineGUID>string</SearchEngineGUID>
<SearchData>base64Binary</SearchData>
</GenericEventSpecialSearchData>
<GenericEventSpecialSearchData>
<SearchEngineGUID>string</SearchEngineGUID>
<SearchData>base64Binary</SearchData>
</GenericEventSpecialSearchData>
</SpecialSearchDataList>

The FaceComparison Element

Face Comparison events extend Generic Events by comparing the image of a known person with a face from a face event near the same time as the Generic Event. Face Comparison events are created when the <FaceComparison> XML is provided to the CreateGenericEvent operation.

<FaceComparison>
<StartTimeReferenceDelta>int</StartTimeReferenceDelta>
<EndTimeReferenceDelta>int</EndTimeReferenceDelta>
<ReferenceImage/>
<CustomFieldName>string</CustomFieldName>
<CustomFieldValue>string</CustomFieldValue>
</FaceComparison>

The following list provides more detail on each child element of <FaceComparison>:

Face Comparison Metadata

  • <StartTimeReferenceDelta> Sets the time to start searching for a face event, relative to the event start time (in milliseconds). To search 5 seconds before the event time, the value is -5000. To search 3.5 seconds after the event time, the value is 3500.

  • <EndTimeReferenceDelta> Sets the time to stop searching for a face event, relative to the event start time (in milliseconds). To search 5 seconds after the event time, the values is 5000. To search 10.5 seconds after the event time, the value is 10500.

  • <ReferenceImage> Provides an alternate face reference image instead of using people in the 3VR system. If this tag is set, the Custom Field tags below are ignored.

  • <CustomFieldName> The Custom Field name used to identify people in the 3VR system. Custom Fields are listed on the Person card in OpCenter, or can be retrieved by the CustomFieldNames operation.

  • <CustomFieldValue> The value of the Custom Field.

If a <ReferenceImage> is used, it should have the same children elements as the <Image> element defined previously (e.g. <Width> <Height> <Format> and so on.)

Extended Generic Event Operations

The following operations are supplemental to the creation of Generic Events. In the XML, these examples would be wrapped in the soap:body part of the envelope. The SOAP header would contain the ServiceToken found in the response from Authenticate.

Channels

Get a list of cameras.

Sample Request

<Channels xmlns="http://3vr.com" />

Sample Response

<ChannelsResponse xmlns="http://3vr.com">
<ChannelsResult>
<ChannelInfo>
<Id>long</Id>
<Name>string</Name>
<DisplayNumber>int</DisplayNumber>
<Identifier>string</Identifier>
<Description>string</Description>
<HostName>string</HostName>
<IsActive>boolean</IsActive>
</ChannelInfo>
<ChannelInfo>
...
</ChannelInfo>
</ChannelsResult>

CustomFieldNames

Get a list of custom field names associated with a person profile in the 3VR system. These can be used when specifying Face Comparison events.

Sample Request

<CustomFieldNames xmlns="http://3vr.com" />

Sample Response

<CustomFieldNamesResponse xmlns="http://3vr.com">
<CustomFieldNamesResult>
<string>string</string>
<string>string</string>
</CustomFieldNamesResult>
</CustomFieldNamesResponse>

DeleteGenericEvent

Delete a generic event from the server with given GUID.

Sample Request

<DeleteGenericEventDefinition xmlns="http://3vr.com">
<guid>string</guid>
</DeleteGenericEventDefinition>

Sample Response

<DeleteGenericEventDefinitionResponse xmlns="http://3vr.com">
<DeleteGenericEventDefinitionResult>String</DeleteGenericEventDefinitionResult>
</DeleteGenericEventDefinitionResponse>

GenericEvent

Get a Generic Event from the server with given GUID.

Sample Request

<GenericEvent xmlns="http://3vr.com">
<GUID>string</GUID>
</GenericEvent>

Sample Response

<GenericEventResponse xmlns="http://3vr.com">
<GenericEventResult>
<GUID>string</GUID>
<EventTime>dateTime</EventTime>
<StartTimeDelta>int</StartTimeDelta>
<EndTimeDelta>int</EndTimeDelta>
<UseServerTime>boolean</UseServerTime>
<ChannelId>long</ChannelId>
<DefinitionGUID>string</DefinitionGUID>
<MetadataList>
<GenericEventMetadata>
<GUID>string</GUID>
<Value>string</Value>
</GenericEventMetadata>
<GenericEventMetadata>
...
</GenericEventMetadata>
</MetadataList>
<Images>
<GenericEventImage>
...
</GenericEventImage>
<GenericEventImage>
...
</GenericEventImage>
</Images>
<SpecialSearchDataList>
<GenericEventSpecialSearchData>
<SearchEngineGUID>string</SearchEngineGUID>
<SearchData>base64Binary</SearchData>
</GenericEventSpecialSearchData>
<GenericEventSpecialSearchData>
...
</GenericEventSpecialSearchData>
<SpecialSearchDataList/>
<CloseEvent>boolean</CloseEvent>
<FaceComparison/>
</GenericEventResult>
</GenericEventResponse>

GenericEventDefinitionByGUID

Find the Generic Event Definition with the provided GUID.

Sample Request

<GenericEventDefinitionByGUID xmlns="http://3vr.com">
<GUID>string</GUID>
</GenericEventDefinitionByGUID>

Sample response

<GenericEventDefinitionByGUIDResponse xmlns="http://3vr.com">
<GenericEventDefinitionByGUIDResult>
<Name>string</Name>
<ShortName>string</ShortName>
<GUID>string</GUID>
<HelpText>string</HelpText>
<MetadataFields>
<MetadataField>
<GUID>string</GUID>
<Name>string</Name>
<Description>string</Description>
<Type>String or Number or DateTime or EnumeratedType</Type>
<DisplayPosition>int</DisplayPosition>
<DisplayFormat>string</DisplayFormat>
<EnumeratedData xsi:nil="true" />
</MetadataField>
<MetadataField>
...
</MetadataField>
</MetadataFields>
</GenericEventDefinitionByGUIDResult>
</GenericEventDefinitionByGUIDResponse>

GenericEventDefinitionsAll

Sample Request

<GenericEventDefinitionsAll xmlns="http://3vr.com" />

Sample Response

<GenericEventDefinitionsAllResponse xmlns="http://3vr.com">
<GenericEventDefinitionsAllResult>
<EventDefinitionData>
<Name>string</Name>
<ShortName>string</ShortName>
<GUID>string</GUID>
<HelpText>string</HelpText>
<MetadataFields>
<MetadataField xsi:nil="true" />
<MetadataField xsi:nil="true" />
</MetadataFields>
</EventDefinitionData>
<EventDefinitionData>
...
</EventDefinitionData>
</GenericEventDefinitionsAllResult>
</GenericEventDefinitionsAllResponse>

GenericEventDefinitionsByName

Find all the generic event definitions with the provided name.

Sample Request

<GenericEventDefinitionsByName xmlns="http://3vr.com">
<name>string</name>
</GenericEventDefinitionsByName>

Sample Response

<GenericEventDefinitionsByNameResponse xmlns="http://3vr.com">
<GenericEventDefinitionsByNameResult>
<EventDefinitionData>
<Name>string</Name>
<ShortName>string</ShortName>
<GUID>string</GUID>
<HelpText>string</HelpText>
<MetadataFields>
<MetadataField xsi:nil="true" />
<MetadataField xsi:nil="true" />
</MetadataFields>
</EventDefinitionData>
<EventDefinitionData>
...
</EventDefinitionData>
</GenericEventDefinitionsByNameResult>
</GenericEventDefinitionsByNameResponse>

UpdateGenericEvent

Update a generic event with new data.

Request Response

<UpdateGenericEvent xmlns="http://3vr.com">
<genericEvent>
<GUID>string</GUID>
<EventTime>dateTime</EventTime>
<StartTimeDelta>int</StartTimeDelta>
<EndTimeDelta>int</EndTimeDelta>
<UseServerTime>boolean</UseServerTime>
<ChannelId>long</ChannelId>
<DefinitionGUID>string</DefinitionGUID>
<MetadataList>
<GenericEventMetadata>
<GUID>string</GUID>
<Value>string</Value>
</GenericEventMetadata>
<GenericEventMetadata>
...
</GenericEventMetadata>
</MetadataList>
<Images>
<GenericEventImage>
...
</GenericEventImage>
</Images>
<SpecialSearchDataList/>
<CloseEvent>boolean</CloseEvent>
<FaceComparison/>
</genericEvent>
</UpdateGenericEvent>

Sample Response

Returns the GUID of the event.

<UpdateGenericEventResponse xmlns="http://3vr.com">
<UpdateGenericEventResult>string</UpdateGenericEventResult>
</UpdateGenericEventResponse>

UpdateGenericEventDefinition

Update an existing Generic Event Definition. GUIDs must match for existing elements.

Sample Request

<UpdateGenericEventDefinition xmlns="http://3vr.com">
<eventDefinition>
<Name>string</Name>
<ShortName>string</ShortName>
<GUID>string</GUID>
<HelpText>string</HelpText>
<MetadataFields>
<MetadataField>
<GUID>string</GUID>
<Name>string</Name>
<Description>string</Description>
<Type>String or Number or DateTime or EnumeratedType</Type>
<DisplayPosition>int</DisplayPosition>
<DisplayFormat>string</DisplayFormat>
<EnumeratedData xsi:nil="true" /> </MetadataField>
<MetadataField>
...
</MetadataField>
</MetadataFields>
</eventDefinition>
</UpdateGenericEventDefinition>

Sample Response

<UpdateGenericEventDefinitionResponse xmlns="http://3vr.com">
<UpdateGenericEventDefinitionResult>
<Name>string</Name>
<ShortName>string</ShortName>
<GUID>string</GUID>
<HelpText>string</HelpText>
<MetadataFields>
<MetadataField>
<GUID>string</GUID>
<Name>string</Name>
<Description>string</Description>
<Type>String or Number or DateTime or EnumeratedType</Type>
<DisplayPosition>int</DisplayPosition>
<DisplayFormat>string</DisplayFormat>
<EnumeratedData xsi:nil="true" />
</MetadataField>
<MetadataField>
...
</MetadataField>
</MetadataFields>
</UpdateGenericEventDefinitionResult>
</UpdateGenericEventDefinitionResponse>

Interface and Data Classes

If you are using a high level language like C#, you may have access to support classes that will serialize and deserialize the XML for you. Here are the data and interface classes for the Generic Event Service.

C# Interface for the IGenericEventService operations

publicinterfaceIGenericEventService {
public interface IGenericEventService{EventDefinitionData CreateGenericEventDe finiti
on(EventDefinitionDataeventDefinition);
EventDefinitionData UpdateGenericEventDefinition(EventDefinitionDataeventDefinition);
EventDefinitionData[] GenericEventDefinitionsByName(string name);
EventDefinitionData GenericEventDefinitionByGuid(string guid);
EventDefinitionData[] GenericEventDefinitionsAll();
string DeleteGenericEventDefinition(string guid);
ChannelInfo[] Channels();
GenericEventData GenericEvent(string guid);
string CreateGenericEvent(GenericEventData genericEvent);
string UpdateGenericEvent(GenericEventData genericEvent);
string DeleteGenericEvent(string guid);
string[] CustomFieldNames();
}

C# classes for IGenericEventService operations

[Serializable]
public class GenericEventData
{
public string Guid;
public DateTime EventTime;
public int StartTimeDelta;
public int EndTimeDelta;
public bool UseServerTime;
public long ChannelId;
public string DefinitionGuid;
public GenericEventMetadata[] MetadataList;
public GenericEventImage[] Images;
public GenericEventSpecialSearchData[] SpecialSearchDataList;
publicbool CloseEvent = true;
public ReferenceComparison FaceComparison;
[Serializable]
public class ReferenceComparison
{
public int StartTimeReferenceDelta;
public int EndTimeReferenceDelta;
public GenericEventImage ReferenceImage;
public string CustomFieldName;
public string CustomFieldValue;
}
[Serializable]
public class GenericEventMetadata
{
public string Guid;
public string Value;
}
[Serializable]
public class EventDefinitionData
{
public string Name;
public string ShortName;
public string Guid;
public string HelpText;
public MetadataField[] MetadataFields;
}
[Serializable]
public classMetadataField
{
public string Guid;
public string Name;
public string Description;
public MetadataType Type;
public int DisplayPosition;
public string DisplayFormat;
public EnumeratedData EnumeratedData;
}
[Serializable]
public class EnumeratedData
{
public string Name;
public string[] Values;
}
[Serializable]
public enum MetadataType
{
String = 1,
Number = 2,
DateTime = 3,
EnumeratedType = 4 }
/// Sensor types
/// Unknown = 0,
/// AnalogCamera = 1, 'Live' input from Hikvision
/// ImageFiles = 2, 'Imported from the UI
/// IPNetworkCamera = 3, 'Live' input from IMF
/// VideoFiles = 4, 'Live' input from FIM
/// UsbCamera = 5, 'Live' input from FIM
[Serializable]
public class ChannelInfo
{
public long Id;
public string Name;
public int DisplayNumber;
public string Identifier;
public string Description;
public string HostName;
public Boolean IsActive;
} [Serializable]
public class GenericEventImage
{
public int Width;
public int Height;
public PictureFormat Format;
public int NominalAspectRatio;
public double AspectRatioAdjustment;
public byte[] ImageBuffer;
public DateTime ImageTime;
public enumPictureFormat
{
Unknown,
Yuv444,
Yuv420,
Grayscale,
GrayscaleRgb,
Rgb,
Jpeg,
Bitmap
}
}
[Serializable]
public class GenericEventSpecialSearchData
{
public string SearchEngineGuid;
public byte[] SearchData;
}

3VR External Query API

Overview

The 3VR External Query API is used to retrieve events from a standalone 3VR system. The 3VR External Query API cannot be used to retrieve information from an Enterprise appliance. These events correspond to the event cards displayed using 3VR's OpCenter UI.

Queries are formed as XML documents called "predicates". A predicate is sent to the 3VR system using an HTTP POST command. In response, the server will send a well-formed RSS 2.0 XML document listing the set of events that match the predicate. Included in the list is a URL for each event.

Using an HTTP GET command, the client can then retrieve detailed information about the event (also in XML form) from that URL. Each event retrieved is a structured object with a set of attached data.

The exchange between client and server is shown here:

All exchanges are secure using HTTP BASIC authentication. The user names and passwords must match users that have been added to your 3VR system using System Manager.

Query Format

To perform the query, the client POSTs the predicate XML to the URL https://[host name]:8080/rss/ where the XML is passed as the URL encoded argument "queryxml" in the request body. (Your programming environment probably has helper functions to perform this POST operation for you. See the sample and helper code for some examples.) The predicate XML will look something like this (the details of each element will be explained in later sections):

<?xml version="1.0" encoding="utf-8"?>
<Predicate>
<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="EventType" />
<Comparison operation="=" />
<ValueOperand type="System.Int" value="1" />
</ComparisonPredicate>
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="Channel.Id" />
<Comparison operation="=" />
<ValueOperand type="System.Int32" value="1" />
</ComparisonPredicate>
<ComparisonPredicate name="&gt;=" isEnabled="True" id="" DistinctIndividualQueries="Fal
se">
<FacetOperand reference="starttime" />
<Comparison operation="&gt;=" /> <RelativeValueOperand type="System.TimeSpan"
value="0:30:0" />
</ComparisonPredicate>
</AndPredicate>
</Predicate>

Query Response

The 3VR appliance will return up to 50 matching events per query. The response will be an RSS 2.0 formatted XML document, like this:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dc="http://purl.org/dc/
elements/1.1/">
<channel>
<title>3VR Events</title>
<link>https://<3vr-server>:8080/index.xml?allalerts=</link>
<description>Events matching the descriptions</description>
<pubDate>8/3/2007 4:50:43 PM</pubDate>
<lastBuildDate>8/3/2007 4:50:43PM</lastBuildDate>
<item>
<title>8/3/2007 4:47:15 PM - 8/3/2007 4:47:49 PM: Motion Event on Camera Camera 1</
title>
<link>http://<3vr-server>:80/event/id</link>
<description>&lt;img alt=http://<3vr-server>:80/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/
images1.24.MFA src="http://<3vr-server>:80/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/images1.24.
MFA" width=120 height=80&gt;&lt;img alt=http://<3vr-server>:80/images/3 _ 8 _ 2007/23/eventtype
_ 1/0/1/images1.25.MFA src="http://<3vr-server>:80/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/
images1.25.MFA" width=120 height=80&gt;&lt;img alt=http://<3vr-server>:80/images/3 _ 8 _ 2007/23/
eventtype _ 1/0/1/images1.26.MFA src="http://<3vr-server>:80/images/3 _ 8 _ 2007/23/eventtype
_ 1/0/1/images1.26.MFA" width=120 height=80&gt;</description>
<pubDate>4:50 PM</pubDate>
</item>
</channel>
</rss>

Most of this XML is intended to allow reasonable output when viewing this XML in a browser. As a programmer, the tag that you're most interested in is the <link> tag under <item>. Each of these contains the URL for the detailed information about that event.

To retrieve the event information, use an HTTP GET command with that URL. The result will be an XML document that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="/eventstylesheet.xsl"?>
<ThreeVRExport version="6.0" date="8/6/2007 10:13:25 AM" server="https://<3vr-server>:8080"
ApplianceGuid="fc8ca7c5-83e7-4b8d-af70-b599b5635509">
<ThreeVREventExport>
<EventCollectionExt>
<Events>
<Event XmlReferenceId="14" StartTime="2007-08-03T16:47:15.7640000-07:00" _ Short-
StartTime="8/3/2007 4:47:15 PM" EndTime="2007-08-03T16:47:49.3060000-07:00" _ ShortEnd-
Time="8/3/2007 4:47:49 PM" Status="Closed" Guid="08c12540-7e74-4d58-bf3f-580771130ddb">
<EventType XmlReferenceId="15" Name="Motion" /> <Appliance XmlReferenceId="16"
Name="<3vr-server>" HostAddress="<3vr-server>" Guid="fc8ca7c5-83e7-4b8d-af70-b599b5635509" />
<Channel XmlReferenceId="17" Name="Camera 1" DisplayNumber="1" ChannelType="AnalogCamera"
Description="" Identifier="analogcamera://1" />
<SpecializedEvent>
<MotionEvent XmlReferenceId="18">
<EventDetails>
<MotionEventDetails XmlReferenceId="19" GridHeight="15" GridWidth="22"
GridPixelAspectRatioAdjustment="1.10000002384186" GridPixelAspectRatioNominal="1">
<OriginationByteArray />
<PresenceByteArray>…</PresenceByteArray>
<DirectionByteArray>…</DirectionByteArray>
<TerminationByteArray />
</MotionEventDetails>
</EventDetails>
<BaseEvent>
<Event XmlReferenceId="14" IsReference="True" />
</BaseEvent>
<UserFrames />
<MotionFrames>
<MotionFrame XmlReferenceId="20" IsUserCreated="False" TimeStamp="8/3/2007
4:47:16 PM">
<Picture XmlReferenceId="21" TimeStamp="2007-08-
03T16:47:16.1700000-07:00" _ ShortTimeStamp="8/3/2007 4:47:16 PM" AspectRatioAdjustment="1"
NominalAspectRatio="1" Width="160" Height="120" ImageWidth="160" ImageHeight="120"
IsAnnotated="False" FilePath="https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/
images1.24.MFA" />
</MotionFrame>
<MotionFrame XmlReferenceId="22" IsUserCreated="False" TimeStamp="8/3/2007
4:47:33 PM">
<Picture XmlReferenceId="23" TimeStamp="2007-08-
03T16:47:33.7850000-07:00" _ ShortTimeStamp="8/3/2007 4:47:33 PM" AspectRatioAdjustment="1"
NominalAspectRatio="1" Width="160" Height="120" ImageWidth="160" ImageHeight="120"
IsAnnotated="False" FilePath="https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/
images1.25.MFA" />
</MotionFrame> <MotionFrame XmlReferenceId="24" IsUserCreated="False"
TimeStamp="8/3/2007 4:47:35 PM"> <Picture XmlReferenceId="25" TimeStamp="2007-08-
03T16:47:35.3950000-07:00" _ ShortTimeStamp="8/3/2007 4:47:35 PM" AspectRatioAdjustment="1"
NominalAspectRatio="1" Width="160" Height="120" ImageWidth="160" ImageHeight="120"
IsAnnotated="False" FilePath="https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/
images1.26.MFA" />
</MotionFrame>
</MotionFrames>
<Videos>
<Video XmlReferenceId="26" StartTime="2007-08-03T16:47:15.7480000-07:00"
_ ShortStartTime="8/3/2007 4:47:15 PM" EndTime="2007-08-03T16:47:45.9150000-07:00" _ Short-
EndTime="8/3/2007 4:47:45 PM" ChannelId="1" PixelAspectRatioAdjustment="1.10000002384186"
PixelAspectRatioNominal="1" Width="352" Height="240" VideoFormat="HikvisionH264"
FilePath="https://<3vr-server>:8080/videos/3 _ 8 _ 2007/23/videos/0/1/0.mpg" />
<Video XmlReferenceId="27" StartTime="2007-08-03T16:47:45.9150000-07:00"
_ ShortStartTime="8/3/2007 4:47:45 PM" EndTime="2007-08-03T16:47:56.3240000-07:00" _ Short-
EndTime="8/3/2007 4:47:56 PM" ChannelId="1" PixelAspectRatioAdjustment="1.10000002384186"
PixelAspectRatioNominal="1" Width="352" Height="240" VideoFormat="HikvisionH264"
FilePath="https://<3vr-server>:8080/videos/3 _ 8 _ 2007/23/videos/0/1/1.mpg" />
</Videos>
</MotionEvent>
</SpecializedEvent>
<TriggeredAlerts />
<MetadataElements />
</Event>
</Events>
</EventCollectionExt>
</ThreeVREventExport>
</ThreeVRExport>

Images and videos associated with the event can also be retrieved by their URL as referenced by the <FilePath> elements.

Predicate Shortcuts with Query Feed

For convenience, the 3VR Query API includes a feature called "Query Feed' that offers set of built-in predicates for certain common queries. This allows client programs to bypass the predicate definition step and obtain a list of matching events with a simple GET request.

Developers familiar with the API for 3VR Software Version 6.0 will recognize the URL paths below, which formerly belonged to an API called the "3VR Event Syndication API." Although these queries still exist in 7.X, in the new software version the 3VR Live Query API was developed to permit continous, real-time event streams. Refer to the "3VR Live Query API" section for more information.

The following built-in queries are available as Query Feeds:

Query

URL

Description

ALL EVENTS

https://[IP address or hostname]:8080/feed/events/all

Returns the most recent events of any type.

MOTION EVENTS

https://[IP address or hostname]:8080/feed/events/motion

Returns the most recent motion events.

FACE EVENTS

https://[IP address or hostname]:8080/feed/events/face

For VIP Appliances with the Facial Surveillance analytic enabled, returns the recent faces captured by the system.

GENERIC EVENTS

https://[IP address or hostname]:8080/feed/events/generic

Returns event types that are not system defaults. This includes:

  • Events created by applications using the External System Activity API

  • Events created by a transaction plug-in, such as the 3VR ATM Data Capture plug-in

  • Events generated by an analytic plug-in, such as VIP License Plate Recognition

ALERTS

https://[IP address or hostname]:8080/feed/alerts

Returns the most recent events that have triggered an alert.

SPECIFIC ALERT

https://[IP address or hostname]:8080/feed/alert/[alertname]

Returns the most recent events that triggered the alert named [alertname].

To return more than one alert name, separate the names with an ampersand (&).

Defining Predicates

Predicates act as the filters that determine which events in the system are returned by a specific request. Predicates act on facets of the events. A facet is a single element, such as the start time of the event or the name of a specific alert that the event triggered. These can be combined to form more complex predicates, for example we may want to retrieve all events with a start time that was in the past hour and that triggered the alert called "Motion in Storage Room."

The XML for a predicate has a simple structure. The XML frame for the predicate looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Predicate>Submitted predicate
</Predicate>

For a complete XML schema of the predicate structure, see the query.xsd file in the SDK.

Each query is a request like this submitted with an HTTP POST command. The Predicate element always has exactly one child, which is the actual predicate. Predicates can be nested when appropriate. For example, an and predicate can contain other predicates but a predicate of type comparison cannot.

An individual predicate has the following form:

<PredType name="name" isEnabled="True" id="" DistinctIndividualQueries="False">
Sub-predicates or components
</PredType>

For example, the predicate described above (looking for events matching both a time and an alert trigger) will be formatted like this:

<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
<ComparisonPredicate name="&gt;" isEnabled="True" id="" DistinctIndividualQueries="False
">
Comparison operands
</ComparisonPredicate>
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
Comparison Operands
</ComparisonPredicate>
</AndPredicate

The most important predicates are the Comparison predicate, which supports filtering by facets, and the and and or predicates which allow you to combine predicates in the obvious ways. In the above example we combine two comparison predicates with an and predicate which is quite common.

Please note that although this section of the documentation explains how to manually format a query, 3VR also provides various libraries to construct XML queries with ease. The use of the libraries will be explained later.

Operands

The Comparison predicate compares two Operands using the supplied comparison. The full expression looks like this:

<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="TriggeredAlerts.Alert.Name" />
<Comparison operation="=" />
<ValueOperand type="System.String" value="Motion in Storage Room" />
</ComparisonPredicate>

Here, the comparison is an equals (=) operation, and the operands are a facet operand and a value operand. The facet operand determines which facet of the event to use in the comparison, in this case, TriggeredAlerts.Alert.Name. Please refer to the section "Predicate Facets Reference" for a description of all available facets.

The value operand represents the value and type of operand with which that facet should be compared. The type defines how the value string will be interpreted; the most common types are System.String, System.Integer, System.Long, System.DateTime, and System.TimeSpan. Unless the value should be parsed as a date, the type selected does not usually matter.

The comparison predicate supports the following comparison operations: =, !=, >, >=, <, <= and LIKE. These work as you would expect with LIKE being a standard SQL LIKE. For strings, using LIKE is the same as using = except '_' matches any character and '%' matches any string of characters. Using LIKE with a value operand of 'Smit%' will match any string that begins with 'Smit'
including Smith and Smits.

In addition to the facet operand and the value operand, the system also supports array value operands and relative value operands. Array value operands allow a set of values to be supplied to the comparison. This is only valid when = is used as the comparison operator. The comparison will succeed if any of the values passed in for the array value operand equal the corresponding facet.

The format of the array value operand looks like this:

<ArrayValueOperand>
<type1 type=" type1" value="value1" />
<type2 type="type2" value="value2" />
… more sub-operands …
</ArrayValueOperand>

For example, if we wanted to extend the above comparison to include events that triggered either a "Motion in Storage Room" alert or a "Motion in Lobby" alert, we can create the following comparison:

<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="TriggeredAlerts.Alert.Name" />
<Comparison operation="=" />
<ArrayValueOperand>
<System.String type="System.String" value="Motion in Storage Room" />
<System.String type="System.String" value="Motion in Lobby" />
</ArrayValueOperand>
</ComparisonPredicate>

Relative value operands allow you to specify operands that are relative to the present. They only work with times. The format for a relative value operand is:

<RelativeValueOperand type="System.TimeSpan" value="hh:mm:ss" />

where hh, mm, and ss are hours, minutes and seconds, respectively. For example, to retrieve all events in the past half hour, use the following comparison:

<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="StartTime" />
<Comparison operation="=" />
<RelativeValueOperand type="System.TimeSpan" value="0:30:00" />
</ComparisonPredicate>

To find all events that occurred between 11PM and 1AM, use the following predicate:

<TimeRangePredicate name="TimeRange" isEnabled="True" id="" DistinctIndividualQueries="Fals
e">
<FacetOperand reference="starttime" />
<ValueOperand type="System.DateTime" value="1/1/2000 11:00 PM" />
<ValueOperand type="System.DateTime" value="1/1/2000 1:00 AM" />
</TimeRangePredicate>

Additional Predicates

While most queries are written using the and, or, and comparison predicates, there are a number of other predicates that are useful for more complex querying.

Disjoint Predicates

Disjoint and and Disjoint or are variants of the and and or predicates. The difference is in the way that they evaluate facets relative to each other. The regular and and or predicates treat multiple references to the same facet name as a reference to the same object in the database. This is very efficient, but sometimes can cause problems.

For example, when you want to query for a generic event which has two separate pieces of metadata (for example, teller ID and account number) set to specific number, the following and predicate will not work:

<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
<!-- subclause 1, teller id = "870-19766" -->
<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="MetaDataElements.MetadataKey.Name" />
<Comparison operation="=" />
<ValueOperand type="System.String" value="Teller ID" />
</ComparisonPredicate>
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="MetaDataElements.MetadataStringValue.StringValue" />
<Comparison operation="=" />
<ValueOperand type="System.String" value="870-19766" />
</ComparisonPredicate>
</AndPredicate>
<!-- subclause 2, account number = "0076 5609 3817" -->
<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="MetaDataElements.MetadataKey.Name" />
<Comparison operation="=" />
<ValueOperand type="System.String" value="Account Number" />
</ComparisonPredicate>
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="MetaDataElements.MetadataStringValue.StringValue" />
<Comparison operation="=" />
<ValueOperand type="System.String" value="0076 5609 3817" />
</ComparisonPredicate>
</AndPredicate>
</AndPredicate>

This does not work because MetaDataElements.MetadataKey.Name refers to the same database entry both times it's mentioned, and cannot equal both "Teller ID" and "Account Number" at the same time.

In order to make this work, we replace the top level with a disjoint and predicate:

<DisjointAndPredicate name="disjointand" isEnabled="True" id="" DistinctIndividualQueries="
False">
<!-- subclause 1, teller id = "870-19766" -->
<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
… Same comparisons as above …
</AndPredicate>
<!-- subclause 2, account number = "0076 5609 3817" -->
<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
… Same comparisons as above …
</AndPredicate>
</DisjointAndPredicate>

The disjoint or predicate works in the same fashion.

The disjoint and and disjoint or predicates are much more expensive in terms of database load than the and and or predicates. For this reason, they should be avoided whenever possible. Often the use of an array value operand will have the same effect and be much more efficient.

Not Predicate

The not predicate inverts the sense of a predicate included under it. For example, to find all events except those for cameras 1 and 2, use the following:

<NotPredicate name="not" isEnabled="True" id="" DistinctIndividualQueries="False">
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="Channel.Id" />
<Comparison operation="=" />
<ArrayValueOperand>
<System.Long type="System.Long" value="1" />
<System.Long type="System.Long" value="2" />
</ArrayValueOperand>
</ComparisonPredicate>
</NotPredicate>

Exists Predicate

The exists predicate determines if some item is in the database at all. For example, to find all events with notes, use this predicate:

<ExistsPredicate name="exists" isEnabled="True" id="" DistinctIndividualQueries="False">
<FacetOperand reference="Notes.Id" />
</ExistsPredicate>

The not exists predicate reverses the sense of exists and is identically structured. Always use this instead of creating a combination of not and exists. Not does not invert exists correctly because of the way that the SQL database works underneath.

Is Null Predicate

The Is Null predicate matches facets that exist, but are null in the database. It is structurally identical to the Exists predicate.

Time Range Predicate

The Time Range predicate allows you to retrieve events that occurred during a specified period during the day. It includes three operands: the facet to check, the beginning of the time range, and the end of the time range. If the end is earlier than the beginning, the time range is assumed to cross midnight. The time is passed as full date/times, but the date component is ignored.

Processing Returned Events

Upon receiving the POST request, 3VR system interprets the predicate, executes the query and sends a response of the summary of matching events in RSS 2.0 format:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dc="http://purl.org/dc/
elements/1.1/">
<channel>
<title>3VR Events</title>
<link>https://<3vr-server>:8080/index.xml?allalerts=</link>
<description>Events matching the descriptions</description>
<pubDate>8/3/2007 4:50:43 PM</pubDate>
<lastBuildDate>8/3/2007 4:50:43PM</lastBuildDate>
<item>
<title>8/3/2007 4:47:15 PM - 8/3/2007 4:47:49 PM: Motion Event on Camera Camera 1</
title>
<link>http://<3vr-server>:80/event?id=1</link>
<description>&lt;img alt=https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype
_ 1/0/1/images1.24.MFA src="https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype
_ 1/0/1/images1.24.MFA" width=120 height=80&gt;&lt;img alt=https://<3vr-server>:8080/
images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/images1.25.MFA src="https://<3vr-server>:8080/images/
3 _ 8 _ 2007/23/eventtype _ 1/0/1/images1.25.MFA" width=120 height=80&gt;&lt;img
alt=https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/images1.26.MFA
src="https://<3vr-server>:8080/images/3 _ 8 _ 2007/23/eventtype _ 1/0/1/images1.26.MFA" width=120
height=80&gt;</description>
<pubDate>4:50 PM</pubDate>
</item>
</channel>
</rss>

Each <item> element represents a matching event.
Most of this response XML is intended to allow a browser to display reasonable output. As a programmer, the tag that you are most interested in is the <link> tag under <item>. Each <link> tag contains the URL for the detailed information about that event.

Since RSS 2.0 format complies with standard XML format, all standard methods for parsing XML, e.g. SAX, DOM, or simply parsing text, can be used to retrieve information from the XML document. Examples can be found in the section "Using Language-specific Libraries to Access the 3VR External Query API".

To retrieve the event information, use an HTTP GET command with the URL in the <link> element. The response XML can be processed using any standard XML parser, and has the following format:

<ThreeVRExport version=version date=queryTime server="" ApplianceGuid=sourceGuid>
<ThreeVREventExport>
<EventCollectionExt>
<Events>
<Event> Property elements </Event>
</Events>
</EventCollectionExt>
</ThreeVREventExport>
</ThreeVRExport>

There will always be only one <Event> element under <Events>. It is a structured object containing all information the 3VR system captured for that event, and all facets of that event will be stored in the elements or attributes.

Example 1: Facet "StartTime" is stored as an attribute in the <Event> tag.
Example 2: Facet "Channel" is stored in a <Channel> element under <Event>.
Example 3: The location of the profile image is an attribute in the <Profile> element under

<SpecializedEvent>, or "/ ThreeVRExport/ThreeVREventExport/EventCollectionExt/Events/Event/SpecializedEvent/FaceEvent/ProfileGroup/CanonicalProfile/Profile/@ImageLocation" as expressed in XPath.

A complete list of XPath for all facets can be found in the final section of this document.

The full XML response for a face event looks like this:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="/eventstylesheet.xsl"?>
<ThreeVRExport version="6.0" date="8/15/2007 10:52:32 AM" server="https://<3vr-server>:8080"
ApplianceGuid="30d53949-fe72-43b6-9429-8bb0e81ffde3">
<ThreeVREventExport>
<EventCollectionExt>
<Events>
<Event XmlReferenceId="0" StartTime="2007-07-18T16:50:53.6740000-07:00" _ Short
StartTime="7/18/2007 4:50:53 PM" EndTime="2007-07-18T16:50:55.3770000-07:00" _ ShortEnd-
Time="7/18/2007 4:50:55 PM" Status="Closed" Guid="9db1d70c-d3a7-499a-97af-c8ca9524e1b4">
<EventType XmlReferenceId="1" Name="Face" />
<Appliance XmlReferenceId="2" Name="Developer Workstation" HostAddress="<3vrserver>"
Guid="30d53949-fe72-43b6-9429-8bb0e81ffde3" />
<Channel XmlReferenceId="3" Name="Camera 1" DisplayNumber="1"
ChannelType="AnalogCamera" Description="" Identifier="analogcamera://1" />
<SpecializedEvent>
<FaceEvent XmlReferenceId="4" FaceEventType="Camera" MatchType="Indexed">
<ProfileGroup XmlReferenceId="5" Guid="1b0c21e5-1657-4f1f-bf1bebbc23f19391"
CreationDate="7/18/2007 4:50:53 PM" UseForAutoMatch="False" Version="67240452">
<CanonicalProfile>
<Profile XmlReferenceId="6" Guid="946d2ead-5461-4a47-9bf1-
634d3a139f29" Quality="0" AspectRatioAdjustment="1.10000002384186" NominalAspectRatio="2"
Width="704" Height="240" ImageWidth="704" ImageHeight="240" FaceLocationX="561.902709960938"
FaceLocationY="101.333190917969" FaceWidth="40.2184638977051" IsAnnotated="False"
ImageTimestamp="2007-07-18T16:50:54.4710000-07:00" _ ShortImageTimestamp="7/18/2007 4:50:54 PM"
ImageLocation="https://<3vr-server>:8080/images/18 _ 7 _ 2007/23/eventtype _ 2/0/1/images1.24.
MFA">
<Bits>…</Bits>
</Profile>
</CanonicalProfile>
<Profiles>
<Profile XmlReferenceId="6" IsReference="True" />
<Profile XmlReferenceId="7" Guid="511e23e4-d3d4-4f76-bc99-
801733b102a3" Quality="0" AspectRatioAdjustment="1.10000002384186" NominalAspectRatio="2"
Width="704" Height="240" ImageWidth="704" ImageHeight="240" FaceLocationX="588.512878417969"
FaceLocationY="119.292823791504" FaceWidth="37.9340286254883" IsAnnotated="False"
ImageTimestamp="2007-07-18T16:50:54.8770000-07:00" _ ShortImageTimestamp="7/18/2007 4:50:54 PM"
ImageLocation="https://<3vr-server>:8080/images/18 _ 7 _ 2007/23/eventtype _ 2/0/1/images1.25.
MFA">
<Bits>…</Bits>
</Profile>
<Profile XmlReferenceId="8" Guid="e763ef30-2315-4917-9d50-
70447662a0a1" Qual ity="0" AspectRatioAdjustment="1.10000002384186" NominalAspectRatio="2"
Width="704" Height="240" ImageWidth="704" ImageHeight="240" FaceLocationX="573.310546875"
FaceLocationY="101.27188873291" FaceWidth="40.6226844787598" IsAnnotated="False"
ImageTimestamp="2007-07-18T16:50:54.5800000-07:00" _ ShortImageTimestamp="7/18/2007 4:50:54 PM"
ImageLocation="https://<3vr-server>:8080/images/18 _ 7 _ 2007/23/eventtype _ 2/0/1/images1.26.
MFA">
<Bits>…</Bits>
</Profile>
</Profiles>
</ProfileGroup>
<BaseEvent>
<Event XmlReferenceId="0" IsReference="True" />
</BaseEvent>
<Frames>
<FaceFrame XmlReferenceId="9" IsSubGroupFrame="False" FaceConfidence="3.91948986053467" FaceLocationX="561.902709960938" FaceLocationY="101.333190917969"
FaceQuality="0" FaceWidth="40.2184638977051" FirstEyeConfidence="3.95001864433289" First-
EyeLocationX="540.107666015625" FirstEyeLocationY="100.637741088867" SecondEyeConfidence="
3.49672865867615" SecondEyeLocationX="580.898864746094" SecondEyeLocationY="
100.739883422852">
<Picture XmlReferenceId="10" TimeStamp="2007-07-
18T16:50:54.4710000-07:00" _ ShortTimeStamp="7/18/2007 4:50:54 PM" AspectRatioAdjustment="
1.10000002384186" NominalAspectRatio="2" Width="704" Height="240" ImageWidth="704" ImageHeight="
240" IsAnnotated="False" FilePath="https://<3vr-server>:8080/images/18 _ 7 _ 2007/23/
eventtype _ 2/0/1/images1.21.MFA" />
</FaceFrame>
<FaceFrame XmlReferenceId="11" IsSubGroupFrame="False" FaceConfidence="
3.1991331577301" FaceLocationX="573.310546875" FaceLocationY="101.27188873291"
FaceQuality="0" FaceWidth="40.6226844787598" FirstEyeConfidence="3.51949620246887"
FirstEyeLocationX="550.122863769531" FirstEyeLocationY="99.4405822753906" SecondEye-
Confidence="2.99968218803406" SecondEyeLocationX="592.0732421875" SecondEyeLocationY="
99.338264465332">
<Picture XmlReferenceId="12" TimeStamp="2007-07-
18T16:50:54.5800000-07:00" _ ShortTimeStamp="7/18/2007 4:50:54 PM" AspectRatioAdjustment="
1.10000002384186" NominalAspectRatio="2" Width="704" Height="240" ImageWidth="704" ImageHeight="
240" IsAnnotated="False" FilePath="https://<3vr-server>:8080/images/18 _ 7 _ 2007/23/
eventtype _ 2/0/1/images1.23.MFA" />
</FaceFrame>
<FaceFrame XmlReferenceId="13" IsSubGroupFrame="False" FaceConfidence="
3.20546126365662" FaceLocationX="588.512878417969" FaceLocationY="119.292823791504"
FaceQuality="0" FaceWidth="37.9340286254883" FirstEyeConfidence="2.94460487365723" First-
EyeLocationX="563.047180175781" FirstEyeLocationY="120.273956298828" SecondEyeConfidence="
3.68825888633728" SecondEyeLocationX="607.244323730469" SecondEyeLocationY="
119.276374816895">
<Picture XmlReferenceId="14" TimeStamp="2007-07-
18T16:50:54.8770000-07:00" _ ShortTimeStamp="7/18/2007 4:50:54 PM" AspectRatioAdjustment="
1.10000002384186" NominalAspectRatio="2" Width="704" Height="240" ImageWidth="704" ImageHeight="
240" IsAnnotated="False" FilePath="https://<3vr-server>:8080/images/18 _ 7 _ 2007/23/
eventtype _ 2/0/1/images1.22.MFA" />
</FaceFrame>
</Frames>
<Videos>
<Video XmlReferenceId="15" StartTime="2007-07-18T16:50:27.5800000-07:00"
_ ShortStartTime="7/18/2007 4:50:27 PM" EndTime="2007-07-18T16:50:59.6110000-07:00" _ Short-
EndTime="7/18/2007 4:50:59 PM" ChannelId="1" PixelAspectRatioAdjustment="1.10000002384186"
PixelAspectRatioNominal="1" Width="352" Height="240" VideoFormat="HikvisionH264"
FilePath="https://<3vr-server>:8080/videos/18 _ 7 _ 2007/23/videos/0/1/17.mpg" />
</Videos>
</FaceEvent>
</SpecializedEvent>
<TriggeredAlerts />
<MetadataElements />
</Event>
</Events>
</EventCollectionExt>
</ThreeVREventExport>
</ThreeVRExport>

Using Language Specific Libraries to Access the 3VR External Query API

3VR provides libraries and samples in various programming languages for easily using the 3VR Query API. You only need to supply a few essential elements to generate query XML. We also provide utility methods to execute the query using POST, return the XML including event details using GET, and parse the XML response.

Language-specific libraries are included (with source code) in the 3VR web services SDK. The 3VR External Query API currently has language support for client programs written in Java and Python. Support for additional languages will be added in the future. Of course, it is possible to directly access the query API from any programming language using XML/HTTP.

3VR External Query API Support for Java Programming

To use 3VR query Java API, add threeVRQuery.jar to your Java project library and import any necessary packages in your Java program.

import com.threeVR.predicate.*

Now you will be able to use predicates to construct the query XML.

// Events that triggered Alert 'My Alert'
Predicate pred = new LikeP("TriggeredAlerts.Alert.Name", "My Alert");
String queryxml = pred.ToXmlString();
// Events that triggered alerts
ExistsPredicate existPred = new ExistsPredicate("TriggeredAlerts.Alert.Id");
queryxml = existPred.ToXmlString();
// Similarity Search
AndP pred = new AndP(new Predicate[] {
new EqP("eventtype", new Integer(2)), new GeP("starttime", starttime),
new LeP("starttime", endtime),
new SimilarityP(null, personids, 0.8f, starttime,endtime)
});
queryXml = pred.ToXmlString();

Once you have generated the query xml, you can perform a POST operation to http://[IP or hostname]/rss to return an XML response which contains a summary of matching events. In the Java library we provide utility methods for performing the POST operation. Here's an example for using that method to easily obtain response XML:

// POST queryXml to https://<3vr-server:port>
String response = Utilities.query(queryXml, "3vr-server", port);

After obtaining response XML for the matching event summary, we can use any standard XML library to process it. Here is an example using JAXP. The Java API for XML Processing (JAXP) is a library that enables applications to parse and transform XML documents independent of a particular XML processing implementation. We can use JAXP6 to parse RSS formatted events summary response.

//JAXP example
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document xmldoc = parser.parse(new InputSource(new StringReader(response)));
NodeList items = xmldoc.getElementsByTagName("item");
for (int i = 0; i < items.getLength(); i++) {
Node item = items.item(i);
NodeList children = item.getChildNodes();
for (int j = 0; j < children.getLength(); j++) {
if (children.item(j).getNodeName().equals("link")) {
String link = children.item(j).getTextContent(); //proceed with link
}
}
}

We also provide examples for processing the response XML by parsing text or using DOM. Examples can be found in Utilities.java.

// Parsing text
public static void processResultsSummary _ Text(String response){…}
// DOM processing
public static void processResultsSummary _ DOM(String response){…}

After processing event summary XML, we can use the content of the <link> element to perform a GET operation and retrieve detail for events of interest. We provide a utility method in Utitlities.java for this purpose.

// use link to do GET and retrieve event detail XML
String eventDetail = Utilities.getEvent(eventLink);

Similarly, after obtaining the event detail XML, it can be processed using any standard XML parser. Examples can be found in Utilities.java.

// using DOM
public static void processFirstEvent _ DOM(String response) {…}
// using JAXP
public static void processFirstEvent _ JAXP(String response) {…}

Combine above examples to query for all motion events in a case named 'Fraud #1', print start time and end time, and image location of key frames:

// Motion events in Case 'Fraud #1'
AndP pred = new AndP(new Predicate[] {
new EqP("eventtype", new Integer(1)),
new EqP("cases.name", "Fraud #1")
});
String response = Utilities.query(pred.ToXmlString());
ArrayList links = Utilities.getAllEventLinks(response);
for (int i = 0; i < links.size(); i++) {
String eventDetail = Utilities.getEvent(links.get(i).toString());
//Parse event details string by DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document xmldoc = parser.parse(new InputSource(new StringReader(eventDetail)));
NodeList events = XPathAPI.selectNodeList(xmldoc, "//Events/Event");
Node event = events.item(0);
String starttime = event.getAttributes().getNamedItem("StartTime").getTextContent();
String endtime = event.getAttributes().getNamedItem("EndTime").getTextContent();
NodeList pictures = XPathAPI.selectNodeList(xmldoc, "//Events/Event/SpecializedEvent/
MotionEvent/MotionFrames/MotionFrame/Picture");
for (int j=0; j<pictures.getLength(); j++) {
Node picture = pictures.item(j);
String filePath = picture.getAttributes().getNamedItem("FilePath").getTextContent();
System.out.println("Frame:" + filePath);
}
}

The source code for this example is in the SDK in the file Samples\EventsInCase.java.

3VR External Query API Support for Python Programming

In the samples\query\python directory of your SDK, there is a Python module, queryapi.py which contains a variety of helper bindings for using the 3VR External Query API. The helpers are divided into two parts: helpers for building predicate XML and helpers for retrieving event XML from a 3VR server using a sequence of HTTP requests.

Building predicates with the Python helpers

The queryapi.py module provides a set of classes that make it very easy and concise to define predicates. These classes can be used to generate the XML that will be sent to server in a POST request and execute the query. For example, the expression

p = andp(eqp('EventType', '1'), gep('StartTime', datetime.timedelta(minutes=20)))

creates a predicate which will find all motion events in the past 20 minutes. This example shows that predicate class names always end with the letter "p"; the three predicates used here are "and," "equals," and "greater than or equals." Note that the last two are really specific types of comparison predicates.

Each predicate class supports the toXml() function which returns the XML to post for that predicate. In the above example, calling p.toXml() returns:

<?xml version="1.0" encoding="utf-8"?>
<Predicate>
<AndPredicate name="and" isEnabled="True" id="" DistinctIndividualQueries="False">
<ComparisonPredicate name="=" isEnabled="True" id="" DistinctIndividualQueries="Fals
e">
<FacetOperand reference="EventType" />
<Comparison operation="=" />
<ValueOperand type="System.Int" value="1" />
</ComparisonPredicate>
<ComparisonPredicate name="&gt;=" isEnabled="True" id="" DistinctIndividualQueries="
False">
<FacetOperand reference="StartTime" />
<Comparison operation="&gt;=" />
<RelativeValueOperand type="System.TimeSpan" value="0:20:0" />
</ComparisonPredicate>
</AndPredicate>
</Predicate>

There are two types of predicate classes: those that contain other predicates (like and and or) and those that contain operands (like equals). In addition, there is a special predicate type which allows you to define searches to find face events with faces similar to given people, profiles or groups of people.

The following table summarizes the available predicate classes and how they correspond to the XML predicate tags:

Predicate classes that contain operands are smart when trying to interpret their operand arguments in ways that are reasonable, sparing the user the pain of defining the type of each operand. The interpretations are as follows:

datetime, date, time and timedelta are defined in the Python standard datetime module. See the Python Library Reference at python.org for details.

Similarity searches can be created with the similarityp class. Similarity searches allow you to query for face events that include faces that are similar to other sets of faces. Usually, this predicate will be used by specifying either a person or group. Person ids can be viewed on the people panel in OpCenter. For example, the following query:

p = similarityp(personids=[10], earliest=datetime.datetime(2007,6,15),
\ minSimilarity=0.7)

will retrieve all face events since June 15, 2007 that are 70% similar to person #10. It is possible to force an interpretation by wrapping the value in facet(), value(), arrayvalue(), or relativevalue() but this is not recommended. In general, all operand predicates should be specified as pred(facet, value).

Retrieving event XML using the Python helpers

The process of executing a query has four parts:

  1. Post the query using an HTTP POST command.

  2. Parse the retrieved event list as RSS-formatted XML, and use HTTP GET commands to retrieve XML for each event.

  3. Process the retrieved events.

  4. If appropriate, retrieve images and/or videos for the event by retrieving links included in the event XML from the server using
    HTTP GET requests.

The queryapi.py module supports this model using the Query class. The Query class performs all necessary HTTP processing and presents the user with a lazily-evaluated array of results. Each element of the results contains the XML for a single event. Because the array is lazily-evaluated, applications that may need to use only a subset of the results can use Query efficiently; only those results that are used are retrieved from the server.

The common idiom for using Query, like many other Python constructs, is to create an instance and then use iteration to process each of the elements as follows (where p is the predicate specified above):

query = Query('<server-name>', p)
for eventString in query:

process event XML string

The XML strings are usually processed with XML parsing tools from the Python library, although in simple cases regular expression matching could be used. The provided samples show parsing in the document-object model (DOM) using the xml.dom.minidom module and event-based (SAX) parsing using the xml.parsers.expat module. The appropriate mechanism depends on your application and preferred programming style. For small applications, minidom provides a convenient interface that does not require you to maintain any parsing state yourself. SAX-style parsing (expat-based parsers in particular) tends to be very high performance, and is, therefore, suitable for bulk processing.

The Query class also supports the len() operation, array indexing and slicing so those methods are available if they are a preferable way to access the query results.

The Query class has a method called getlink() which takes a URL and returns that object retrieved from the server. This is used to retrieve images and videos from the server using the resource identification link embedded in the event XML.

Python sample applications

Included in the SDK are two sample applications which show how to use the queryapi.py module to get real data.

The sample alerts.py displays all events that generated alerts in the past day. For each event, the program prints the camera number, the event start time, and the name of the triggered alert to the standard output. This sample uses the mini DOM module to parse the events.

The sample images.py returns events that generated alerts in the last day and saves all the images from those events in the folder specified on the command line. This sample uses the expat SAX parser to process the events. It also demonstrates using the getlink() function to retrieve image data.

3VR Live Query API

Overview

The 3VR Live Query API allows users to receive a continuously updating stream of events matching a predicate. The 3VR Appliance will return events matching the predicate as long as a connection remains open between client and server.

Query Format

The format of the predicate for the 3VR Live Query API is identical to the 3VR External Query API. To perform the query, the client POSTs the predicate XML to the URL https://[IP address or host name]/live/ where the XML is passed as the URL encoded argument "queryxml".

Live Query Response

The response from the Live Query API will be a continuously updating series of events. Each event takes the form of <item> elements:

<item>
<title>8/7/2012 1:48:10 PM -07:00 - 8/7/2012 1:48:14 PM -07:00: Motion Event on Camera
Hallway East</title>
<link>http://10.100.2.202:80/event/2413380</link>
<description>
<img alt="http:s//10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/eventtyp
e _ 1/E _ 1 _ 20120807 _ 130135 _ 001.535.MFA2" src="https://10.100.2.202:8080/
image/s/2012 _ 08 _ 07/13/eventtype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.535.MFA2"
width="120" height="80" />;<img alt="https://10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/
eventtype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.536.MFA2" src="https://10.100.2.202:8080/
image/s/2012 _ 08 _ 07/13/eventtype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.536.MFA2" width="120"
height="80" />;<img alt="https://10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/eventtype _ 1
/E _ 1 _ 20120807 _ 130135 _ 001.537.MFA2" src="https://10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/eve
nttype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.537.MFA2" width="120" height="80" />;</description>
<pubDate>1:49 PM</pubDate>
</item>
<item>
<title>8/7/2012 1:48:07 PM -07:00 - 8/7/2012 1:48:09 PM -07:00: Motion Event on Camera
Hallway East</title>
<link>https://10.100.2.202:8080/event/2413379</link>
<description>
<img alt="http:s//10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/eventtyp
e _ 1/E _ 1 _ 20120807 _ 130135 _ 001.528.MFA2" src="https://10.100.2.202:8080/
image/s/2012 _ 08 _ 07/13/eventtype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.528.MFA2"
width="120" height="80" />;<img alt="https://10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/
eventtype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.529.MFA2" src="https://10.100.2.202:8080/
image/s/2012 _ 08 _ 07/13/eventtype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.529.MFA2" width="120"
height="80" />;<img alt="https://10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/eventtype _ 1
/E _ 1 _ 20120807 _ 130135 _ 001.530.MFA2" src="https://10.100.2.202:8080/image/s/2012 _ 08 _ 07/13/eve
nttype _ 1/E _ 1 _ 20120807 _ 130135 _ 001.530.MFA2" width="120" height="80" />;</description>
<pubDate>1:49 PM</pubDate>
</item>

The <item> element here is identical to the <item> child element in the Query API response.

Sample Python Code

In this example, we use the queryapi.py module to obtain a live query feed of alerts with a given alert name.

from queryapi import *
import urllib2
def yield _ url(url):
for line in urllib2.urlopen(url):
if line is not "":
yield line
def LiveQuery(hostname, query):
Request = urllib2.Request
password _ mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
handler = urllib2.HTTPBasicAuthHandler(password _ mgr)
opener = urllib2.build _ opener(handler)
urllib2.install _ opener(opener)
theurl = 'http://%s/live' % (hostname)
m = re.match('(http://[^/]+)', theurl)
rooturl = m.group(1)
password _ mgr.add _ password(None, rooturl, "techrep", "3MeDeee")
postdata = query
req = Request(theurl, postdata, {})
returned _ xml = ""
in _ event = False
for line in yield _ url(req):
if line.startswith('</ThreeVRExport'):
in _ event = False
returned _ xml += line.rstrip('\n')
yield returned _ xml
returned _ xml = ""
if in _ event:
returned _ xml += line.rstrip('\n')
if line.startswith('<ThreeVRExport'):
in _ event = True
returned _ xml += line.rstrip('\n')
if _ _ name _ _ == "_ _ main _ _":
try:
hostname = sys.argv[1]
alertname = sys.argv[2]
except:
print "usage: livealert.py [IP address or hostname] [alertname]"
sys.exit(1)
query = andp(eqp('TriggeredAlerts.Alert.Name',sys.argv[2]), eqp('Status', 20))
for xmlbit in LiveQuery(hostname, query.toXml()):
print 'There was a matching alert!'
# here you may process the returned xml with a Python library such as
# minidom or Beautiful Soup

Predicate Facets Reference

About Facets

A 3VR event is a structured object. It contains a collection of facets, each containing a piece of information like start time, channel, etc. A facet can contain primitive value or a structured object of a specific type.

Facets are used in two ways in the 3VR APIs:

  • A dotted facet name is used in predicates to define the part of the event that needs to be tested. For example, we can use the string "Appliance.Name" to refer to the name facet of the appliance facet when constructing predicate XML. Here we have a sequence of facets (each representing a layer of objects) separated by periods.

  • The attributes and elements of the event structure XML represent facets. These correspond (almost exactly) to the facets used in the predicates, but the way you'll access them depends on the way you're parsing the event XML. In this section, we use XPath notation to specify the path of elements to the particular facet. Note: DOM and SAX parsing will access the paths differently.

Event Facets

Here is the list of facets in the event object:

As mentioned above, we use the dotted facet name in predicates. That is, if a facet contains an object, we use the dot operator (period) to refer to the facets of that object. For example, EventType returns the type of event associated to the event; TriggeredAlerts.Alert.Name returns the name of triggered alerts associated with the event.

There is no maximum length for dotted facet names. The elements of the dotted facet name are NOT case-sensitive. However, every facet in the chain must exist in the object it relates to. An invalid facet will produce HTTP error results.

The one difference between the way facet names are used in the predicate and in the XML is with respect to SpecializedEvent objects. In the XML, SpecializedEvent is a wrapper for a specific type of event object (MotionEvent, FaceEvent, ImportedImageEvent, or GenericEvent). Each of these types is represented by a different XML object and schema component. When creating a predicate, you can simply skip this intermediate event and refer directly to its components.

For example, to build a predicate based on the value of the person's first name, you'd use the facet SpecializedEvent. ProfileGroup.Person.FirstName but to retrieve the first name from the returned XML you'd use the XPath/SpecializedEvent/FaceEvent/ProfileGroup/Person/@FirstName. In the latter case, we explicitly mention the FaceEvent tag that occurs in the XML but is not necessary in the predicate.

Complete list of all Facets for 3VR Objects

  • No labels