-
Notifications
You must be signed in to change notification settings - Fork 9
Use Cases
- Login to a VideoXpert system
- Get devices from a VideoXpert system
- Get devices, and filter results from a VideoXpert system
- Get datasources from a device
- Get an RTSP URI from a datasource
- Create an Mjpeg datasession
- Get the current exports on a VideoXpert system
- Get the current exports using a filter on a VideoXpert system
- Create and delete exports
- Acquire the ptz controller to initiate ptz actions
- Get the presets for a specific data source
- Get the patterns for a specific data source
- Trigger a preset or pattern
- Get existing clips from VideoXpert
- Get existing clips from VideoXpert, filtered by a time range
- Pan, tilt and zoom a datasource
- Situations and Events
- Get a list of Situations from VideoXpert and delete them as necessary
- Get a filtered list of Situations from VideoXpert and delete them as necessary
- Add a new Situation (event type) to VideoXpert
- Inject events into VideoXpert
#include "VxSdk.h"
// Init the sdk with your key generated using VxSdkKeyGen.exe
VxSdk::VxInit("Some long key");
// Enter the VideoXpert login information
VxSdk::VxLoginInfo loginInfo;
VxSdk::Utilities::StrCopySafe(loginInfo.ipAddress, "192.168.1.1");
VxSdk::Utilities::StrCopySafe(loginInfo.username, "admin");
VxSdk::Utilities::StrCopySafe(loginInfo.password, "admin");
loginInfo.port = 443;
loginInfo.ssl = true;
// Attempt to login to the system
VxSdk::IVxSystem* system = nullptr;
VxSdk::VxResult::Value result = VxSdk::VxSystemLogin(loginInfo, system);
if(result == VxSdk::VxResult::kOK) {
// Successfully logged in
// Delete system object
system->Delete();
system = nullptr;
}
else {
// Unsuccessfully logged in
}
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Create a collection of device objects
VxSdk::VxCollection<VxSdk::IVxDevice**> devices;
// Make the GetDevices call, which will return with the total device count, this allows the client to allocate memory.
VxSdk::VxResult::Value result = system->GetDevices(devices);
// Unless there are no devices on the system, this should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// An array of pointers is allocated using the size returned by the previous GetDevices call
devices.collection = new VxSdk::IVxDevice*[devices.collectionSize];
result = system->GetDevices(devices);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < devices.collectionSize; i++) {
VxSdk::IVxDevice* device = devices.collection[i];
// It is up to the caller to delete the devices returned by GetDevices
device->Delete();
device = nullptr;
}
}
// Delete the array of devices previously allocated
delete[] devices.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Create a collection of device objects
VxSdk::VxCollection<VxSdk::IVxDevice**> devices;
// This type of filtering can be done on any VxSdk::VxCollection object
// Create two filters to return the top 50 results, starting from device 5
devices.filterSize = 2;
VxSdk::VxCollectionFilter filters[2];
devices.filters = filters;
devices.filters[0].key = VxSdk::VxCollectionFilterItem::kCount;
VxSdk::Utilities::StrCopySafe(devices.filters[0].value, "50");
devices.filters[1].key = VxSdk::VxCollectionFilterItem::kStart;
VxSdk::Utilities::StrCopySafe(devices.filters[1].value, "5");
// Make the GetDevices call, which will return with the total device count (50 or less), this allows the client to allocate memory.
VxSdk::VxResult::Value result = system->GetDevices(devices);
// Unless there are no devices on the system, this should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// An array of pointers is allocated using the size returned by the previous GetDevices call
devices.collection = new VxSdk::IVxDevice*[devices.collectionSize];
result = system->GetDevices(devices);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < devices.collectionSize; i++) {
VxSdk::IVxDevice* device = devices.collection[i];
// It is up to the caller to delete the devices returned by GetDevices
device->Delete();
device = nullptr;
}
}
// Delete the array of devices previously allocated
delete[] devices.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxDevice device object (see 03-GetDevices.cpp)
// Create a collection of datasource objects
VxSdk::VxCollection<VxSdk::IVxDataSource**> dataSources;
VxSdk::VxResult::Value result = device->GetDataSources(dataSources);
// Unless there are no datasources on the system, this should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// An array of pointers is allocated using the size returned by the previous GetDataSources call
dataSources.collection = new VxSdk::IVxDataSource*[dataSources.collectionSize];
result = device->GetDataSources(dataSources);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < dataSources.collectionSize; i++) {
VxSdk::IVxDataSource* dataSource = dataSources.collection[i];
// It is up to the caller to delete the datasources returned by GetDataSources
dataSource->Delete();
dataSource = nullptr;
}
}
// Delete the array of devices previously allocated
delete[] dataSources.collection;
}
An example of how to control an RTSP live/recorded stream can be found here: Example RTSP commands.
#include "VxSdk.h"
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
int size = 0;
char* endpoint = nullptr;
VxSdk::VxResult::Value result = datasource->GetRtspEndpoint(endpoint, size);
// If the rtsp uri is not available on the datasource the result will return VxSdk::VxResult::kActionUnavailable,
// otherwise VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
endpoint = new char[size];
// Now that our endpoint buffer is large enough, call the method again to fill it.
result = datasource->GetRtspEndpoint(endpoint, size);
if(result == VxSdk::VxResult::kOK) {
// We now have a proper RTSP uri to stream live/recorded video at 'endpoint'
// Live video is played by simply streaming the RTSP uri provided.
// Recorded video is played by calling RTSP commands on the RTSP endpoint.
}
// Clean up our own memory
delete endpoint;
}
#include "VxSdk.h"
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
VxSdk::IVxDataSession* dataSession = nullptr;
VxSdk::VxResult::Value result = datasource->CreateMjpegDataSession(dataSession);
// If the mjpeg protocol is not available on the datasource the result will return VxSdk::VxResult::kActionUnavailable,
// otherwise VxSdk::VxResult::kOK
if (result == VxSdk::VxResult::kOK) {
// The jpeg uri can be found at the jpegUri
// If the gap between jpegUri calls is too large the session will self terminate and another dataSession will be required
dataSession->jpegUri;
// To seek the datasession to a time in the past to play recorded video, call Seek and pass in the unix timestamp
dataSession->Seek(446284800);
// Set the rate at which to playback the mjpeg pull stream.
// -2 = reverse @ 2x
// -1 = reverse @ 1x
// 0 = pause
// 1 = forward @ 1x
// 2 = forward @ 2x
dataSession->SetSpeed(1);
// Transfer back to the live stream from this recorded stream seeked at 446284800
dataSession->GoLive();
dataSession->SetSpeed(1);
// Delete the datasession from the system, now that we are closing down
dataSession->DeleteDataSession();
// It is up to the caller to delete the dataSession returned by CreateMjpegDataSession
dataSession->Delete();
dataSession = nullptr;
}
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Create a collection of export objects
VxSdk::VxCollection<VxSdk::IVxExport**> exports;
// Make a call to GetExports to get the size
VxSdk::VxResult::Value result = system->GetExports(exports);
// Unless there are no exports on the system, this should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// An array of pointers is allocated using the size returned by the previous GetExports call
exports.collection = new VxSdk::IVxExport*[exports.collectionSize];
result = system->GetExports(exports);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < exports.collectionSize; i++) {
VxSdk::IVxExport* myExport = exports.collection[i];
// It is up to the caller to delete the export returned by GetExports
myExport->Delete();
myExport = nullptr;
}
}
// Cleanup our memory
delete[] exports.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Create a collection of export objects
VxSdk::VxCollection<VxSdk::IVxExport**> exports;
// This type of filtering can be done on any VxSdk::VxCollection object
// Create one filter to return exports with a specific name
exports.filterSize = 1;
VxSdk::VxCollectionFilter filters[1];
exports.filters = filters;
exports.filters[0].key = VxSdk::VxCollectionFilterItem::kName;
VxSdk::Utilities::StrCopySafe(exports.filters[0].value, "My Investigation");
// Make a call to GetExports to get the size
VxSdk::VxResult::Value result = system->GetExports(exports);
// Unless there are no exports on the system matching the filter name, this should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// An array of pointers is allocated using the size returned by the previous GetExports call
exports.collection = new VxSdk::IVxExport*[exports.collectionSize];
result = system->GetExports(exports);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < exports.collectionSize; i++) {
VxSdk::IVxExport* myExport = exports.collection[i];
// It is up to the caller to delete the export returned by GetExports
myExport->Delete();
myExport = nullptr;
}
}
// Cleanup our memory
delete[] exports.collection;
}
In VideoXpert exports are created client side and initiated server side, this means the client can start an export and then routinely poll the server until it's completed, then download the export. Make sure to get the clips before creating an export so that you know video exists in the time range before attempting to export (see 16-GetClips.cpp).
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
// We will create two clips to be exported using the same dataSource (you may use multiple dataSources as long as they are attached
// to the same VideoXpert system)
VxSdk::VxNewExportClip clips[2];
VxSdk::Utilities::StrCopySafe(clips[0].dataSourceId, datasource->id);
VxSdk::Utilities::StrCopySafe(clips[0].startTime, "2015-09-09T12:10:00Z");
VxSdk::Utilities::StrCopySafe(clips[0].endTime, "2015-09-09T12:10:30Z");
VxSdk::Utilities::StrCopySafe(clips[1].dataSourceId, datasource->id);
VxSdk::Utilities::StrCopySafe(clips[1].startTime, "2015-09-09T13:10:00Z");
VxSdk::Utilities::StrCopySafe(clips[1].endTime, "2015-09-09T13:10:30Z");
VxSdk::VxNewExport newExport;
newExport.format = VxSdk::VxExportFormat::kMp4;
// Arbitrary name for the export
VxSdk::Utilities::StrCopySafe(newExport.name, "My Investigation");
// If the password field has a password set then the export will be password protected, if the VxSdk::VxNewExport::password is not
// set, the export will be public
VxSdk::Utilities::StrCopySafe(newExport.password, "super_secret");
newExport.clips = &clips;
newExport.clipSize = 2;
VxSdk::IVxExport* exportItem = nullptr;
VxSdk::VxResult::Value result = system->CreateExport(newExport, exportItem);
// Unless there was an issue initiating the export the result should be VxSdk::VxResult::kOK
if (result == VxSdk::VxResult::kOK) {
// The exportItem returned from the system is the export initiated on the server and contains a lot of helpful information about the export
// To delete this newly created export (or any export on the system - See: 09-GetExports.cpp) simply make a DeleteExport call
result = exportItem->DeleteExport();
// Unless there was an issue deleting the export the result should be VxSdk::VxResult::kOK
// This export item must still be deleted from memory
exportItem->Delete();
exportItem = nullptr;
}
#include "VxSdk.h"
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
// Check to ensure this datasource is a ptz camera
bool isPtz;
VxSdk::VxResult::Value result = dataSource->CanPtz(isPtz);
if(isPtz) {
// Get the ptz controller which allows the client to make ptz calls
VxSdk::IVxPtzController* ptzController = nullptr;
result = datasource->GetPtzController(ptzController);
if (result == VxSdk::VxResult::kOK) {
// Successfully got the ptz controller
// Delete the ptz controller object
ptzController->Delete();
ptzController = nullptr;
}
else {
// Failed to acquire the ptz controller for this datasource, it's possible that this data
}
}
#include "VxSdk.h"
// Get a VxSdk::IVxPtzController ptzController object (see 12-GetPtzController.cpp)
VxSdk::VxCollection<VxSdk::IVxPreset**> presets;
VxSdk::VxResult::Value result = ptzController->GetPresets(presets);
// As long as the datasource has at least one preset the GetPresets call should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// Fill the array of pointers to the proper size as determined by the previous GetPresets call
presets.collection = new VxSdk::IVxPreset*[presets.collectionSize];
result = ptzController->GetPresets(presets);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < presets.collectionSize; i++) {
VxSdk::IVxPreset* preset = presets.collection[i];
// It's up to the caller to delete each of the presets returned by the sdk
preset->Delete();
preset = nullptr;
}
}
// Delete the memory allocated earlier
delete[] presets.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxPtzController ptzController object (see 12-GetPtzController.cpp)
VxSdk::VxCollection<VxSdk::IVxPattern**> patterns;
VxSdk::VxResult::Value result = ptzController->GetPatterns(patterns);
// As long as the datasource has at least one pattern the GetPatterns call should return VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// Fill the array of pointers to the proper size as determined by the previous GetPatterns call
patterns.collection = new VxSdk::IVxPattern*[patterns.collectionSize];
result = ptzController->GetPatterns(patterns);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < patterns.collectionSize; i++) {
VxSdk::IVxPattern* pattern = patterns.collection[i];
// It's up to the caller to delete each of the patterns returned by the sdk
pattern->Delete();
pattern = nullptr;
}
}
// Delete the memory allocated earlier
delete[] patterns.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxPtzController ptzController object (see 12-GetPtzController.cpp)
// Get a VxSdk::IVxPreset preset object (see 13-GetPresets.cpp)
// Get a VxSdk::IVxPattern pattern object (see 14-GetPatterns.cpp)
// Trigger a preset
VxSdk::VxResult::Value result = ptzController->TriggerPreset(*preset);
// Trigger a pattern
result = ptzController->TriggerPattern(*pattern);
Getting the clips for a particular datasource tells the client how much recorded video exists for the datasource. For instance a clip might exist from Monday to Friday, and another clip from Sunday until the current time. This would indicate that recording was interrupted for some reason on friday and wasn't restored until Sunday.
Knowing the date/time of existing recordings is also necessary when a user wants to export a time range, when exporting a time range must be selected where video actually exists. It may be faster to make a filtered get clips call if you want to check if recordings exist at a specific time (see 16-Filter-GetClips.cpp).
#include "VxSdk.h"
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
VxSdk::VxCollection<VxSdk::IVxClip**> clips;
VxSdk::VxResult::Value result = datasource->GetClips(clips);
// As long as there are clips from this datasource the result should be VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// Allocate the required amount of memory
clips.collection = new VxSdk::IVxClip*[clips.collectionSize];
result = datasource->GetClips(clips);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < clips.collectionSize; i++) {
IVxClip* clip = clips.collection[i];
// It's up to the caller to delete the memory allocated for each clip
clip->Delete();
clip = nullptr;
}
}
// Delete the memory allocated earlier
delete[] clips.collection;
}
Getting the clips for a particular datasource tells the client how much recorded video exists for the datasource. For instance a clip might exist from Monday to Friday, and another clip from Sunday until the current time. This would indicate that recording was interrupted for some reason on friday and wasn't restored until Sunday.
Knowing the date/time of existing recordings is also necessary when a user wants to export a time range, when exporting a time range must be selected where video actually exists.
#include "VxSdk.h"
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
VxSdk::VxCollection<VxSdk::IVxClip**> clips;
// Create two filters to return clips between a start and endtime
clips.filterSize = 2;
VxSdk::VxCollectionFilter filters[2];
clips.filters = filters;
clips.filters[0].key = VxSdk::VxCollectionFilterItem::kSearchStartTime;
VxSdk::Utilities::StrCopySafe(clips.filters[0].value, "2015-09-09T13:00:00Z");
clips.filters[1].key = VxSdk::VxCollectionFilterItem::kSearchEndTime;
VxSdk::Utilities::StrCopySafe(clips.filters[1].value, "2015-09-09T13:10:00Z");
VxSdk::VxResult::Value result = datasource->GetClips(clips);
// As long as there are clips in this filtered response from this datasource the result should be VxSdk::VxResult::kInsufficientSize
if(result == VxSdk::VxResult::kInsufficientSize) {
// Allocate the required amount of memory
clips.collection = new VxSdk::IVxClip*[clips.collectionSize];
result = datasource->GetClips(clips);
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < clips.collectionSize; i++) {
IVxClip* clip = clips.collection[i];
// It's up to the caller to delete the memory allocated for each clip
clip->Delete();
clip = nullptr;
}
}
// Delete the memory allocated earlier
delete[] clips.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxPtzController ptzController object (see 12-GetPtzController.cpp)
// Move the camera to the right at 100% velocity, and don't alter the zoom
VxSdk::VxResult::Value result = ptzController->ContinuousMove(100, 0, VxSdk::VxZoomDirection::kNone);
// Move the camera to the left at 100% velocity, and don't alter the zoom
result = ptzController->ContinuousMove(-100, 0, VxSdk::VxZoomDirection::kNone);
// Move the camera up and right at 100% velocity, and don't alter the zoom
result = ptzController->ContinuousMove(100, 100, VxSdk::VxZoomDirection::kNone);
// Some other methods include...
// AbsoluteMove
// AbsolutePan
// AbsoluteTilt
// AbsoluteZoom
// RelativeMove
// Alternatively you can call the convenience method
result = ptzController->PtzStop();
Understanding how Situations relate to Events can be difficult to comprehend at first, but make sense as you get familiar with them.
-
Situation - Basically a Situation is an Event type. For instance 'external/pelco/person_crossing_a_line' might be a Situation. A developer could think of a Situation as a class. The Situation must be in the format of 'external/{company_name}/{situation_type}'
-
Event - An Event is essentially an instance of a Situation. So when someone crosses a line this Event will be associated with the 'external/pelco/person_crossing_a_line' Situation. A developer could think of an Event as an object of class Situation.
Note: Cameras are linked to Situations, Events are associated with situations.
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
// Create a collection of IVxSituation to be populated by the sdk
VxSdk::VxCollection<VxSdk::IVxSituation**> situations;
VxSdk::VxResult::Value result = system->GetSituations(situations);
// The result should be kInsufficientSize if the number of situations on the system are greater than 0 (always)
if(result == VxSdk::VxResult::kInsufficientSize) {
// Allocate enough space for the IVxSituation collection
situations.collection = new VxSdk::IVxSituation*[situations.collectionSize];
result = system->GetSituations(situations);
// The result should now be kOK since we have allocated enough space
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < situations.collectionSize; i++) {
IVxSituation* situation = situations.collection[i];
// Link this situation to an IVxDataSource (or IVxDevice), so that they are tied together on an event
// You can link together as many IVxDataSource or IVxDevice's as you want
situation->Link(*datasource);
// UnLink an IVxDataSource (or IVxDevice) from this situation
situation->UnLink(*datasource);
// Delete this Situation from the server
situation->DeleteSituation();
// Free the memory
situation->Delete();
situation = nullptr;
}
}
// Remove the memory we previously allocated to the collection
delete[] situations.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Get a VxSdk::IVxDataSource datasource object (see 05-GetDataSources.cpp)
// Create a collection of IVxSituation to be populated by the sdk
VxSdk::VxCollection<VxSdk::IVxSituation**> situations;
// Create a filter to return just the Situation we are looking for
VxSdk::VxCollectionFilter filters[1];
situations.filterSize = 1;
situations.filters = filters;
situations.filters->key = VxSdk::VxCollectionFilterItem::kType;
VxSdk::Utilities::StrCopySafe(filters->value, "external/pelco/person_crossing_a_line");
VxSdk::VxResult::Value result = system->GetSituations(situations);
// The result should be kInsufficientSize if the number of situations on the system are greater than 0 (not always when filtering)
if(result == VxSdk::VxResult::kInsufficientSize) {
// Allocate enough space for the IVxSituation collection
situations.collection = new VxSdk::IVxSituation*[situations.collectionSize];
result = system->GetSituations(situations);
// The result should now be kOK since we have allocated enough space
if(result == VxSdk::VxResult::kOK) {
for (int i = 0; i < situations.collectionSize; i++) {
IVxSituation* situation = situations.collection[i];
// Link this situation to an IVxDataSource (or IVxDevice), so that they are tied together on an event
// You can link together as many IVxDataSource or IVxDevice's as you want
situation->Link(*datasource);
// UnLink an IVxDataSource (or IVxDevice) from this situation
situation->UnLink(*datasource);
// Delete this Situation from the server
situation->DeleteSituation();
// Free the memory
situation->Delete();
situation = nullptr;
}
}
// Remove the memory we previously allocated to the collection
delete[] situations.collection;
}
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Create a situation object
VxSdk::VxNewSituation situation;
// Use the Default() helper method to set the situation fields to their defaults
// Careful, this method allocates memory to situation.snoozeIntervals that we must own
situation.Default();
// Specify the situation type
VxSdk::Utilities::StrCopySafe(situation.type, "external/pelco/person_crossing_a_line");
// Specify a friendly name
VxSdk::Utilities::StrCopySafe(situation.name, "Person Crossing a Line");
// Make the call to insert the situation into VideoXpert
VxSdk::VxResult::Value result = system->AddSituation(situation);
if(result == VxSdk::VxResult::kOK) {
// Success
}
else {
// Failure
}
// Delete the memory allocated in the Default method
delete[] situation.snoozeIntervals;
#include "VxSdk.h"
// Get a VxSdk::IVxSystem system object (see 02-Login.cpp)
// Get a VxSdk::IVxSituation situation object (see 21-Filter-GetDeleteSituation.cpp)
// Create a new VxNewEvent object containing the information you wish to be associated with the event
VxSdk::VxNewEvent newEvent;
// Associate this event with a situation type (see 19-Situations&Events.txt)
VxSdk::Utilities::StrCopySafe(newEvent.situationType, situation->type);
// Optional: Unique identifier of the device that generated this event. This field may be omitted if the generator device is
// the same as the source device. Note that this device may be an external device that is not represented in the system
VxSdk::Utilities::StrCopySafe(newEvent.generatorDeviceId, "building_1_event_mgr");
// Unique identifier of the device that the situation occurred on. Note that this device may be an external device that is not
// represented in the system.
VxSdk::Utilities::StrCopySafe(newEvent.sourceDeviceId, "building_1_gate_2");
// Time when the event occurred
VxSdk::Utilities::StrCopySafe(newEvent.time, "2015-09-24T14:10:00Z");
// Specify how many arbitrary pieces of key/value information to associate with the event
newEvent.propertySize = 2;
VxSdk::VxKvObject props[2];
newEvent.properties = props;
VxSdk::Utilities::StrCopySafe(newEvent.properties[0].key, "arbitrary key 1");
VxSdk::Utilities::StrCopySafe(newEvent.properties[0].value, "arbitrary value 1");
VxSdk::Utilities::StrCopySafe(newEvent.properties[1].key, "arbitrary key 2");
VxSdk::Utilities::StrCopySafe(newEvent.properties[1].value, "arbitrary value 2");
// Attempt to insert the event into VideoXpert, the result should return kOK when successful
VxSdk::VxResult::Value result = system->InsertEvent(newEvent);