Introduction to Configuration API

With the System Configuration API, you can add hardware and devices, where devices are considered to be with cameras, inputs, outputs, microphones, speakers and metadata.

You can configure most settings for these devices and add them into specific groups.

Group manipulation is also possible, for example you can add/remove groups and member content.

The two main scenarios covered by this functionality are:

Bulk import of cameras: If a customer is about to upgrade from another system, you can develop a batch program to port the main camera related configuration from previous system. This can be hardware and camera names, IP address, username password, type of hardware, resolution, frame rate etc.

Daily adding of cameras: If a customer needs to add cameras on a continuous basis, or needs to bulk change specific settings for many cameras, then the administrator could create rules and groups while the cameras could be added via programming based on some key input parameters.

Purpose and goals for System Configuration API

The key purpose for the System Configuration API is to open up for modification of the configuration from a program. The System Configuration API is intended to be flexible enough to cover all Milestone VMS products over time, while still be backwards compatible.

This require the interface to be flexible in terms of structure, type of items, hierarchy, commands and many other details. We will cover these topics later on in this document.

Because we expect to add more support in the System Configuration API for each new release of XProtect, the developer should consider being relaxed about new items and new properties. Items defined by the ConfigurationItem class contain a set of property definitions (Value and definition) - to assist you when you work on these, even when you do not really know what they are. The intention here is to support new properties being defined on the server side for a given version. Also, an application that uses the System Configuration API can use the property definition to show label, default value, make range checking etc – to ensure a decent default behavior for properties that are not recognized.

As an example, the set of valid camera resolutions for a camera can vary depending on the camera model, and a set of valid resolutions are therefore included in the description of this property so that the program (or related user-interface, if visible) can display these as a dropdown or validate them.

The actual API is a SOAP service running on the management server with only 14 methods. The intention is to stay with these methods and not add new methods when new types of items need to be supported.

Introduction to the System Configuration API classes

All classes used in the documentation are generated on the server side. You should not implement any new classes that inherit from the System Configuration API classes, because the serialization / de-serialization will ignore any new fields.

When you add new hardware or create new groups, this is always performed through a call to the server. Do not try to attempt filling out the item path because it will be different for each XProtect VMS product.

Introduction to key fields

Path: contains a string that uniquely identifies a ConfigurationItem (always constructed server side), the top level path is "/" and will provide a ConfigurationItem describing the management server.

ItemType: defines the type of ConfigurationItem, the static class ItemTypes contains current known types.

TranslationId: An id to be used for lookup of translated string in the Dictionary returned by the GetTranslation method (when available). When the dictionary does not contain the TranslationId, use the DisplayName.

IConfigurationService

The interface exposed on the management server. The interface currently contains 14 methods to get ConfigurationItem, children, method definitions, and methods to delete, validate changes and set changes to existing ConfigurationItems.

All configuration information is contained in the classes: ConfigurationItem and Property.

GetTranslations() method returns a Dictionary for translations. The key is always the TranslationId defined on a specific class.

GetMethodInfos() method gets all defined methods on this server. Each ConfigurationItem will contain a list of MethodId's for the methods relevant on that item.

On the interface, you find a number of methods to get, set and delete ConfigurationItems, and a InvokeMethod method when other actions must be performed in relation to a ConfigurationItem, for example adding/removing a child item.

The InvokeMethod will return a ConfigurationItem that is not really a piece of configuration, but rather the information that needs to be filled in to execute the MethodId. This ConfigurationItem could in turn also contain another set of MethodId's and properties.

The sequence of ConfigurationItems used for InvokeMethod can be considered the information you would add to a set of wizard pages to get a complete set of information.

See later in this document for more on method/invoke handling.

ConfigurationItem

A class that contains information for one item. It may also contain a number of children that are filled or not filled initially depending on what type of item it is.

Typically a ConfigurationItem contains enough information to be displayed in a list or treeview, identify it for further processing and the key properties own directly on this item.

When getting a list of ConfigurationItems, the list will most often not contain any children, indicated by property ChildrenFilled == false. If more detail information is required, a program should recursively iterate through the ConfigurationItems and get missing children.

The ItemType field contains the type of Item, as defined in ItemTypes – for example ItemType.Camera for a camera device.

If the ConfigurationItem is an item that can be disabled/enabled, the EnableProperty will contain a EnablePropertyInfo class with a few detailed fields.

A ConfigurationItem can also be a grouping item. If so, the ItemCategory field will identify it as ItemCategories.Group. This is an internal group and not something you create, but a logical grouping of settings. One sample of this is how the detailed settings for a camera is divided into multiple groups, much like the tabs are constructed in the Management Client.

Figure 1: A ConfigurationItem for a stream definition with 5 properties. The ItemCategory is "ChildItem", so this ConfigurationItem needs to be updated in conjunction with its parent.

Property

Defines a property and all relevant information needed to display and validate the value content.

The property type is defined by the ValueType, as defined in the static class ValueTypes. The Key field is the identification of the field and the Value field contains the actual value as a string.

For user interface interaction, use the DisplayName for display of a label, the SortKey for sorting the properties, and the UIImportance to identify if this is a normal property, a password property, a hidden property (Check the static class UIImportance for more), and the value should be interpreted according to the ValueType.

The ValueType and ValueTypeInfos combined define how to show and validate the Property.Value.

The Key field can have 2 different formats:

You use the first format for most properties while you use the second format for properties related to specific camera settings.

When you need to identify and find a specific field, use one of the samples to dump a current configuration. Be aware that the properties formatted in the second format can vary from camera to camera and you must be careful handling them if a Key is not available.

Also, in a few places you will have a different referenceId for what looks to be the same property. That can happened for e.g. "Brightness" where this setting on one camera just happens to be different from another camera.

Figure 2: A sample of property content for an Enum property with three possible values.

 

Figure 3: A sample where the Key fields was generated for one specific camera model, formatted as noted in [2] in the picture above.

 

ValueType

Defines the value content of a Property. The types that are available currently are defined in the static class ValueTypes, with additional limitation defined in the ValueTypeInfos array.

For ValueType == String, there are no ValueTypeInfos, but most others will have a definition of min and max values, or a list to be used for e.g. ValueType == Enum.

If the ValueType == Path, then the value is a full Path to another ConfigurationItem.

ValueTypeInfo

Assisting information for displaying and validating value of a property. The ValueTypeInfo.Name defines what info this is about, for example a "MinValue" defines that the ValueTypeInfo.Value is the minimum allowed value for the Property.

EnablePropertyInfo

Is stored on ConfigurationItem.EnableProperty when the item can be enabled or disabled. The class contains a UIToFollowEnable field used to define if a disabled ConfigurationItem should also disable user entry as well as a DisplayName and TranslationId to be used for user interface display. The actual label is not always "Enabled".

MethodInfo

Defines a method that you can invoke. A method is typically an "Add" or "Remove" method defined on a specific ConfigurationItem. The MethodInfo has a MethodId to link with a given ConfigurationItem and to issue the InvokeMethod() call on the System Configuration API.

It also contains an icon/bitmap that you can use for context menu, if available.

Each ConfigurationItem contains a list of MethodId’s that are valid for that specific item.

ValidateResult

Is returned when calling SetItem() or ValidateItem(). If the ValidateResult.ValidatedOk is true, the ConfigurationItem is valid, and the ValidateResult.ResultItem may contain an updated version of the ConfigurationItem used in the call. This may happened when setting one property, could result in other properties to change value.

When the ValidateResult.ValidatedOk is false, the ValidateResult.ErrorResult contains an ErrorResult.

ErrorResult

The ErrorResult contains a description of what is incorrect, and – when relevant – a key of the property in error.

InvokeInfoProperty

Defines a short set of keys used for Property classes, placed on the ConfigurationItem, returned by the MethodInvoke. The keys are predefined to assist the application to handle more complex tasks such as when adding new hardware. In that case, the server will start the process and return a ConfigurationItem with initial information (Progress = 0, State=InProgress), and as the application calls again and again, the Property list in the returned ConfigurationItem will change until the State=Success or State=Error. And then other properties explain the outcome, error code or a path to a newly added hardware.

StringListType

Represents a list of strings or a list of lists of strings. The contents of the list (either strings or sub-lists) are separated by a semicolon (;), and items in the list are separated by a comma (,). Exceptions are marked by a backslash (\), for when you want to use a semicolon, comma, or backslash in the list or list item.

For example:

12-18,tag1,name1;19-36,tag2,name2\,name2;37-42,tag3,name3;

results in the following lists:

12-18 tag1 name1 19-36 tag2 name2,name2 37-42 tag3 name3

Constant classes

These classes contain a set of predefined values for the fields that are named the same as the class.

  • UIHints
  • InvokeInfoStates
  • ItemCategories
  • ItemTypes
  • UIImportance
  • ValueTypeInfoNames
  • ValueTypes
  • AddHardwareErrorCodes

Method of operation

Search / lookup

The ConfigurationItem to start with is the one returned by asking for path = "/".

This will return a ConfigurationItem describing the Management Server itself, like:

From here, children are fetched via the GetChildren(parentPath) method call recursive – as deep as it makes sense.

Try to limit the amount of configuration loaded to what is used.

You can use the ConfigAPIClient sample to study the hierarchy, and item types and to avoid entire leafs not needed to explore. An example could be that the list of all drivers is probably only used when adding new hardware.

For the current version of XProtect VMS, the hierarchy alternates between a real item and a folder, like:

Item with Management Server
      x-folder
          x-item-1
              a-folder
                  a-item-1
              b-folder
                  b-item-1
          x-item-2
      y-folder
          y-item-1
          y-item-2
      z-folder
          z-item-1

This is done to have only the same ItemTypes of ConfigurationItems in one folder, while multiple types of ItemType can exist as children of a real item.

When a ConfigurationItem is received, child items can be filled by using these lines:


private static void FillChildren(ConfigurationItem item)
{
    if (!item.ChildrenFilled)
    {
        item.Children = client.GetChildItems(item.Path);
        item.ChildrenFilled = true;
    }
    if (item.Children == null)
        item.Children = new ConfigurationItem[0];
}

This will then save fetched items in the same hierarchy and avoid re-loading the same items multiple times.

While generally items fetched this way will be identical to items fetched individually by id, there are exceptions, see Roles Folder, below.

Update

Updating is done on ConfigurationItems with ItemCategory == Item. When the category is a group or a ChildItem, it can normally not be updated.

A ConfigurationItem containing the settings for a camera contains a set of ConfigurationItems with ItemCategory == ChildItem, and these will be updated in one method call, e.g. the ConfigurationItem with ItemCategory == Item and all its child items are saved in one operation.

Method and Invoke handling

To perform server side functions, methods are used. The idea here is that the server will own construction of all new items, their properties and all built-in class properties. This is to ensure that not all client applications need to understand every little detail each system might have, in regards to properties and their default values.

All add, remove and construction of child items is done on the server side.

All the methods known by a specific server, are defined in the result returned by GetMethodInfos() on the System Configuration API.

As methods are ‘executed’ on a specific ConfigurationItem, each ConfigurationItem defines what methods are valid in its MethodIds array.

Executing of a method is done on the System Configuration API like:

ConfigurationItem result = client.InvokeMethod(item, methodId);

Where the 'item' is the ConfigurationItem needs to execute 'methodId', for example on 'RECORDER-25' execute 'AddNewHardware'. Note that no parameters are present at this point, it comes in next step.

The result describes the result of the execution of the method. If the MethodId requires parameters, then the result will be a ConfigurationItem with ItemType == InvokeInfo.

Figure 4: ConfigurationItem with ItemType as InvokeInfo

The Properties contain the parameters needed to perform the server side method.

 

The client application should now fill the Value field on these properties and issue a new client.InvokeMethod(result, result.MethodIds[0] ).That will then again ask the server to execute the first method on the ConfigurationItem returned by the initial call.

Note that there might be multiple MethodIds available such as "Back" or "Skip" or "Next".

Figure 5: ConfigurationItem with ItemType as InvokeResult.

Now the resulting ConfigurationItem has ItemType == InvokeResult. This means that the server has initiated and perhaps completed the executing. In the above sample, it was a MethodId for adding new hardware, and the server creates a server side task to perform this.

When the ItemType is InvokeResult, the properties are identified by the keys defined in the static class InvokeInfoProperty:


public static class InvokeInfoProperty
{
    public const string Progress = "Progress";
    public const string Path = "Path";
    public const string ErrorCode = "ErrorCode";
    public const string ErrorText = "ErrorText";
    public const string State = "State";
}

Note that not all properties are available all the time.

The client application can now ask for progress once in a while, by saving the Path returned in the InvokeResult, and by calling the GetItem( path ) for an updated state. The returned ConfigurationItem has the Properties field filled with properties of Key’s as defined in the InvokeInfoProperty class. The result handling should be something like this:


If State == "Success" or State == "Error" then
    We are complete – check for errors, or pick a new Path (identifying the add hardware in this case)
    Do not call for further updates
Else
If State == "Idle" then
    Task has not yet started on the server (consider to only do a slow polling of state)
Else
If State == "InProgress" then
    Check Progress property for how far it is (a value from 0 to 100)
Else
If State == "Completed" then
    You have asked for a task that no longer exists on the server, the final state was returned when the state was "Success" or "Error".

You could check every 3-5 seconds for progress on the task. The task information exists until it has reported an error or success.

Rules configuration

Supported features

Currently (XProtect 2020 R3), the rule support in the Configuration API covers all functionality supported by the XProtect rule engine, with the following exceptions:

Event sources

  • For the System Monitor - server category, only Management Server and Recording Servers can be selected.

Conditions

  • All conditions are supported.

Actions

  • The following actions are not supported (all others are):

    • Send notification to profile
    • Show access request notification
    • Change password on hardware devices
    • Play audio message on devices with priority
  • Plug-in defined actions:

    • Only those taking as parameters either build-in items (like cameras, microphones, etc) or MIP items that are stored in the database, are supported.
    • Actions that use on-the-fly items generated by the plug-in (like e.g. the BAT action sample) are not supported.

ConfigurationItems related to rules

ConfigurationItems related to rules are similar to other ConfigurationItems. The following example creates a rule that records always on a specific camera.


private static void CreateRule()
{
    string ruleId = Guid.NewGuid().ToString();
    string rulePath = string.Format("Rule[{0}]", ruleId);

    var rule = new ConfigurationItem();
    rule.ItemCategory = ItemCategories.Item;
    rule.ItemType = ItemTypes.Rule;
    rule.ParentPath = "/RuleFolder";
    rule.Path = rulePath;
    rule.EnableProperty = new EnablePropertyInfo { Enabled = true };
    rule.Properties = new Property[11];
    rule.Properties[0] = new Property { Key = "Name", Value = "Record Always" };
    rule.Properties[1] = new Property { Key = "Description", Value = "Recording always on camera(s)" };
    rule.Properties[2] = new Property { Key = "StartRuleType", Value = "TimeInterval" };
    rule.Properties[3] = new Property { Key = "Id", Value = ruleId };
    rule.Properties[4] = new Property { Key = "Always", Value = "True" };
    rule.Properties[5] = new Property { Key = "StartActions", Value = "StartRecording" };
    rule.Properties[6] = new Property { Key = "Start.StartRecording.Delay", Value = "0" };
    rule.Properties[7] = new Property { Key = "Start.StartRecording.DeviceIds", Value = "Camera[2d02638a-f661-4258-9226-f9bd24f0d272]" };
    rule.Properties[8] = new Property { Key = "StopActions", Value = "StopRecording" };
    rule.Properties[9] = new Property { Key = "Stop.StopRecording.DeviceIds", Value = "Camera[2d02638a-f661-4258-9226-f9bd24f0d272]" };
    rule.Properties[10] = new Property { Key = "StopRuleType", Value = "TimeInterval" };
}

Variables in rule actions

A few rule actions allow you to enter variables in String properties. The variables are related to the rule itself and to what triggered the rule. The variables are resolved runtime when the action is executed.

Action description StartAction Properties where variables can be used

Create bookmark on <devices>

SetBookmark

Start.SetBookmark.Header

Start.SetBookmark.Description

Make new <log entry>

CreateLogEntry

Start.CreateLogEntry.Text

These variables can be used:

  • $DeviceName$
  • $EventName$
  • $RecorderName$
  • $RuleName$
  • $TriggerTime$

Triggering device and Device from metadata

In some cases, the device(s) that an action should apply to cannot be determined when you create the rule.

  • The action should apply to the specific device that was the source of an event, but the rule is triggered from a group event source, e.g. motion detection events from a camera group.
  • The rule is triggered by an event that is not a device event. The device(s) that the action should apply to is identified by metadata in the event.

The device that triggered an action can be referred to in the rule by using a path created from the ItemType and the special GUID string "00000000-0000-0000-0000-000000000000", e.g. "Camera[00000000-0000-0000-0000-000000000000]".

Events can identify the device(s) that an action should apply to by providing the path in metadata. To indicate that the actual path should be retrieved from metadata, use a path created from the ItemType and the special GUID string "11111111-1111-1111-1111-111111111111", e.g. "Camera[11111111-1111-1111-1111-111111111111]".

External Events sources

The External Events category comprises Generic Events (received through UDP or TCP), User-defined Events (usually generated using plug-in or component integrations), and a small number of Predefined Events.

As for any other event category, event sources (StartEventSources or StopEventSources) must be selected. For External Events, you must use the ItemType "External" with the special GUID string "e8bd6cee-1119-4296-ba91-e3803e2c591e", i.e. "External[e8bd6cee-1119-4296-ba91-e3803e2c591e]".

Access Control groups

Access Control units are not grouped the way hardware devices can belong to one or more groups. Rather, the individual Access Control units in an Access Control system are organized in a hierarchy. An Access Control unit, e.g. a door controller, can also be the parent of other Access Control units, e.g. the two sides of the door. If you create a rule using the path of an Access Control unit for the event source, you will only see events from Access Control unit itself, not its descendants.

The Configuration API represents the group that comprises an Access Control unit and all its descendants by the value of the "RuleGroup" property of the ConfigurationItem for the Access Control unit. The value of the "RuleGroup" property has this form: "AccessControlRuleGroup[7f20ddf0-5803-b43f-81a5-9f7601875c09]".

SiteId property in TriggerEventOnRemoteSite action

The TriggerEventOnRemoteSite action uses the property Start.TriggerEventOnRemoteSite.SiteId.

Set the SiteId property to a path created from the ItemType "Site" and the GUID string that identifies the site, e.g. "Site[E743DD58-E77C-4425-8A09-F5F503F4D879]". Get this GUID string from the Id property of the ConfigurationItem for the site. The current site ConfigurationItem has the item path "/".

If the SiteId property is not defined or empty, the Id for the current site will be used.

Exception handling

A set of exceptions can happen for almost all methods on the ConfigurationAPI, we suggest you have a common exception that handles these.

Check the specific exceptions in namespace:

VideoOS.ConfigurationAPI.ConfigurationFaultException

Also note that underlying TCP sessions might be closed if idle or IIS decided to, so when connection exception happens, it is recommended to retry once.

Login and authentication process

Authentication of users for XProtect VMS can be either AD users or basic users as defined in the XProtect Management Client.

For basic users, the scheme must be HTTPS, while for AD users it is HTTP.

The user and password information is stored as http for basic users, and using NTLM (Windows) for AD users.

The path is then:

http://1.2.3.4/ManagementServer/ConfigurationApiService.svc - for AD users
https://1.2.3.4/ManagementServer/ConfigurationApiService.svc - for basic users

When using default port numbers (for example 80, 443).

The user needs to have management authorization to access the interface.

Sample code for construction of a client proxy:


if (BasicUser)
    uriString = string.Format("https://{0}/ManagementServer/ConfigurationApiService.svc", address);
else
    uriString = string.Format("http://{0}/ManagementServer/ConfigurationApiService.svc", address);

ChannelFactory<IConfigurationService> channel = null;
Uri uri = new UriBuilder(uriString).Uri;
channel = new ChannelFactory<IConfigurationService>(GetBinding(BasicUser), new EndpointAddress(uri,
                EndpointIdentity.CreateSpnIdentity("host/localhost")));

The username and password could be initialized by:


if (BasicUser)
{
    // Note the domain == [BASIC]
    channel.Credentials.UserName.UserName = "[BASIC]\\" + Username;
    channel.Credentials.UserName.Password = Password;
    channel.Credentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
    {
        CertificateValidationMode = X509CertificateValidationMode.None,
    };
}
else
{
    channel.Credentials.Windows.ClientCredential.UserName = Username;
    channel.Credentials.Windows.ClientCredential.Password = Password;
}

Now the channel can be created:

_client = channel.CreateChannel();

Getting started using the System Configuration API

Proxy Generation

If you would like to make your own client based on a WSDL file, you can get it from a running XProtect Management Server with this URL:

http://1.2.3.4/ManagementServer/ConfigurationApiService.svc?wsdl

Samples for the System Configuration API

Samples for the System Configuration API are located under the Component samples and have a start name of "ConfigAPI....".

The ConfigAPIClient is a larger sample that is a primitive version of the XProtect Management Client, which can be used to display and understand the hierarchy of ConfigurationItems, how properties can be handled, how hardware can be added, and many other details.

Extended information on Configuration API objects

Alarm definitions

Alarm definitions can be retrieved through the Config API, but with the limitations of alarms which has certain event type group. See the list below for an overview of the event type groups which are not supported:

Unsupported event type groups

  • AccessControlCategoryEventGroup
  • AccessControlEventGroup
  • LprEventsGroup
  • TransactEventsGroup

Roles Folder

Note that calling GetChildItems on the Roles folder will return Roles without ClientProfile and TimeProfile values. Calling GetItem with the path of the specific individual role will fetch the Role configuration item including these properties. This is done because there is a performance penalty to including these profile ids in the return value, and doing so for a large list of roles could potentially cause timeouts.

Privacy Protection

Setting privacy protection for a camera through the Configuration API requires providing an XML defining the mask. This XML has to conform to this schema.

Support profile overview

Methods reserved for future use

The following methods on the IConfigurationService are reserved for future use:

  • GetDependantItems
  • DeleteItem
  • HasChildItems
  • ConstructItem
  • ConstructChildItem
  • GetItems

Relevant samples

Component integration

Plug-in integration