...
Launch 3VR System Manager.
In the Configure panel of System Manager, right-click the name of the appliance and select Start Web Services.
A pop up will appear indicating that web services is now running.
...
Code Block |
---|
{ "AuthenticateResponse": "PasswordIncorrect", "Message": "Invalid user name or password" } |
The following table lists the possible responses:
...
AuthenticateResponse | Message |
---|---|
Error | An unknown error has encountered during authentication |
PasswordExpired | The password for account ‘[User name]’ has expired. Please create a new password. |
OperationTimeout | Authentication timed out |
PasswordIncorrect | Invalid user name or password |
MaxInactivityTimeExceeded | User ‘[User name]’ suspended:exceeded [number] days of inactivity. |
MaxSignInAttemtpsExceeded | User ‘[User name]’ suspended:exceeded[number] authentication attempts |
NoSignInPermission | User ‘[User name]’ has no permission to sign in. |
NeedsPasswordChange | The password for ‘{User name}’ needs to be changes before it can be properly authenticated |
Port
The 3VR REST API runs on port 8080 and uses SSL, so the server can be accessed via:
...
Code Block |
---|
https://[IP address or hostname]:[port]/enterprisehealth |
...
Sample XML Response
Code Block | ||
---|---|---|
| ||
<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*
Code Block |
---|
https://[IP address or hostname]:[port]/appliancemetadata |
...
Sample XML Response
Code Block | ||
---|---|---|
| ||
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*
Code Block |
---|
https://[IP address or hostname]:[port]/settings |
...
Sample XML Response
Code Block | ||
---|---|---|
| ||
<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*
Code Block |
---|
https://[IP address or hostname]:[port]/settingvalue |
...
Sample XML Response
Code Block | ||
---|---|---|
| ||
<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*
Code Block |
---|
https://[IP address or hostname]:[port]/channelinfo |
...
Code Block | ||
---|---|---|
| ||
<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
Code Block |
---|
https://[IP address or hostname]:[port]/hosts |
...
Sample XML Response
Code Block | ||
---|---|---|
| ||
<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/*
Code Block |
---|
https://[IP address or hostname]:[port]/person/ |
...
Sample XML Response
Code Block | ||
---|---|---|
| ||
<?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
Code Block |
---|
https://[IP address or hostname]:[port]/livevideo |
...
Code Block |
---|
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.
...
The following list provides more detail on each child element of <FaceComparison>:
Face Comparison Metadata
<StartTimeReferenceDelta> <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> <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> <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> <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> <CustomFieldValue> The value of the Custom Field.
...
Query | URL | Description |
---|---|---|
ALL EVENTS | Returns the most recent events of any type. | |
MOTION EVENTS | Returns the most recent motion events. | |
FACE EVENTS | For VIP Appliances with the Facial Surveillance analytic enabled, returns the recent faces captured by the system. | |
GENERIC EVENTS | Returns event types that are not system defaults. This includes:
| |
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 (&). |
...
Code Block | ||
---|---|---|
| ||
<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:
Code Block | ||
---|---|---|
| ||
<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:
Code Block |
---|
<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.
Info |
---|
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:
Code Block | ||
---|---|---|
| ||
<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:
Code Block | ||
---|---|---|
| ||
<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:
Code Block | ||
---|---|---|
| ||
<?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><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><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><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></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:
Code Block | ||
---|---|---|
| ||
<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:
Code Block | ||
---|---|---|
| ||
<?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.
Code Block | ||
---|---|---|
| ||
import com.threeVR.predicate.* |
Now you will be able to use predicates to construct the query XML.
Code Block | ||
---|---|---|
| ||
// 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:
Code Block |
---|
// 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.
Code Block | ||
---|---|---|
| ||
//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.
Code Block | ||
---|---|---|
| ||
// 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.
Code Block | ||
---|---|---|
| ||
// 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.
Code Block | ||
---|---|---|
| ||
// 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:
Code Block | ||
---|---|---|
| ||
// 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
Code Block | ||
---|---|---|
| ||
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:
Code Block |
---|
<?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=">=" isEnabled="True" id="" DistinctIndividualQueries="
False">
<FacetOperand reference="StartTime" />
<Comparison operation=">=" />
<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:
Argument Type | Operand Type |
---|---|
String | As the first argument, a FacetOperand with that name. As the second argument, a ValueOperand of type “System.String” with that value. |
int | A ValueOperand of type “System.Int32” |
datetime, date, or time | A valueOperand of type “System.DateTime” |
timedelta | A RelativeValueOperand that contains the delta specified with the type “System.TimeSpan” |
Any type with an iterator (such a list or tuple) | An ArrayValueOperand containing the elements. |
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:
Code Block | ||
---|---|---|
| ||
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:
Post the query using an HTTP POST command.
Parse the retrieved event list as RSS-formatted XML, and use HTTP GET commands to retrieve XML for each event.
Process the retrieved events.
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):
Code Block | ||
---|---|---|
| ||
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:
Code Block | ||
---|---|---|
| ||
<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.
Code Block | ||
---|---|---|
| ||
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
...