Skip to content

platform sdk enrolling a video unit

Andre Lafleur edited this page Oct 9, 2026 · 6 revisions

Enrolling a video unit

Enroll an IP camera, encoder, video server, generic stream, or offline device as a video unit on a running Archiver role. After successful enrollment, the unit appears as a VideoUnit entity, its Camera entities are visible in the system, and the EnrollmentStatusChanged event is raised on Engine.VideoUnitManager with EnrollmentResult.Added.

Prerequisites

Enrollment requires these conditions and information:

  • The Media SDK license option must be enabled on the system.
  • The target ArchiverRole must be running.
  • The logged-on user must hold the Add video units privilege.
  • You must know the unit's manufacturer name and product type, plus the address, credentials, or product-specific values required by that product.

The examples use an Engine that is already logged on to Security Center and the identifier of the target Archiver role, archiverRoleGuid. Add these namespace imports to your application:

using System;
using System.Linq;
using System.Net;
using System.Security;
using System.Threading.Tasks;
using Genetec.Sdk;
using Genetec.Sdk.Entities.Video;
using Genetec.Sdk.Workflows.UnitManager;

Procedure

Follow these steps to enroll a video unit:

  1. Subscribe to the enrollment status event on IVideoUnitManager before sending the request. Only units enrolled by this session raise the event; subscribing afterward can miss the result.

    engine.VideoUnitManager.EnrollmentStatusChanged += (sender, e) =>
    {
        Console.WriteLine($"Address: {e.Address}, result: {e.EnrollmentResult}");
        if (e.EnrollmentResult == EnrollmentResult.Added)
            Console.WriteLine($"Enrolled unit guid: {e.Unit}");
    };
  2. Discover the product information for the target manufacturer. FindProductsByManufacturer returns a VideoUnitProductInfo for each product type the manufacturer reports; select the product you want to enroll. Get valid manufacturer names from engine.VideoUnitManager.Manufacturers. Use the returned product object so the request retains its product information and capabilities.

    VideoUnitProductInfo productInfo = engine.VideoUnitManager.FindProductsByManufacturer("Axis")
        .FirstOrDefault(p => p.ProductType == "M3045-V");
    
    if (productInfo == null)
        throw new InvalidOperationException("The Axis M3045-V product is not available.");
  3. Build an AddVideoUnitInfo with the unit's address and credentials, and then send the enrollment request to the Archiver role. Pass useDefaultCredentials: false when supplying an explicit username and password. The example uses NetworkCredential.SecurePassword to convert a plaintext password to a SecureString. AddUnitResponse reports whether the request was accepted; the actual enrollment outcome arrives through the event.

    var endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.50"), 80);
    
    var unitInfo = new AddVideoUnitInfo(productInfo, endpoint, useDefaultCredentials: false)
    {
        UserName = "admin",
        Password = new NetworkCredential("", "admin-password").SecurePassword,
    };
    
    AddUnitResponse response = await engine.VideoUnitManager.AddVideoUnit(unitInfo, archiverRoleGuid);
    
    if (response.Error != Error.None)
        Console.WriteLine($"Request rejected: {response.Error}, missing: {response.MissingInformation}");
  4. Wait until EnrollmentStatusChanged is raised with EnrollmentResult.Added. The event is also raised for progress, such as EnrollmentResult.Connecting, so wait for a terminal result rather than the first notification: Added is success, and values such as BadLogin, LicenseError, Timeout, AlreadyAdded, and AlreadyExistingElsewhere are terminal failures. Only after Added is the new VideoUnit reachable through engine.GetEntity<VideoUnit>.

Product-specific enrollment values

VideoUnitProductInfo.ProductCapability.SpecialFeatures lists the additional values required by a product. Supply each listed key in AddVideoUnitInfo.SpecialFeatures. A missing key returns Error.MissingInformation with MissingInformation.SpecialFeature.

Generic Stream units receive video through the real-time streaming protocol (RTSP) or the real-time transport protocol (RTP). The RTP products receive packets over the user datagram protocol (UDP). Offline device units import recorded files. These products require these keys:

Manufacturer Product type Required keys Values
Generic Stream RTSP, RTSP (No ping) StreamUri The complete RTSP URI, including the host, optional port, and stream path.
Generic Stream RTP Unicast Udp, RTP Unicast Udp (No ping) Codec H.265/HEVC, H.264, MPEG-4, or MJPEG.
Generic Stream RTP Multicast Codec The codec of the published multicast stream.
Generic Stream RTP Multicast (No ping) UnitName, Codec A name for the unit and the codec of the published multicast stream.
Offline device Network share UnitName, Path A unique unit name and a local or network folder accessible to the Archiver role.

For both multicast products, use one of the codec values listed for RTP Unicast Udp. Configure the camera's multicast address and port separately to match the publisher.

Each method below takes a logged-on Engine and the target Archiver role identifier. Subscribe to EnrollmentStatusChanged before calling the method, check the returned AddUnitResponse, and wait for EnrollmentResult.Added as described in the procedure. An accepted request does not confirm that video is available.

Enrolling an RTSP stream

Select Generic Stream and RTSP (No ping) to enroll an RTSP server without Internet control message protocol (ICMP) reachability checks. Supply the full stream URI through StreamUri and pass the server's credentials separately. For example, use rtsp://192.168.1.50:8554/loading-bay. The loopback endpoint satisfies the enrollment request's address parameter; the connection uses the host and port in StreamUri.

public static Task<AddUnitResponse> EnrollRtspStreamAsync(
    Engine engine, Guid archiverRoleGuid, string streamUri, string username, SecureString password)
{
    VideoUnitProductInfo productInfo = engine.VideoUnitManager.FindProductsByManufacturer("Generic Stream")
        .FirstOrDefault(p => p.ProductType == "RTSP (No ping)");

    if (productInfo == null)
        throw new InvalidOperationException("The Generic Stream RTSP (No ping) product is not available.");

    var unitInfo = new AddVideoUnitInfo(productInfo, new IPEndPoint(IPAddress.Loopback, 554), useDefaultCredentials: false)
    {
        UserName = username,
        Password = password,
    };
    unitInfo.SpecialFeatures["StreamUri"] = streamUri;

    return engine.VideoUnitManager.AddVideoUnit(unitInfo, archiverRoleGuid);
}

Enrolling an RTP unicast stream

Select Generic Stream and RTP Unicast Udp for a publisher that sends H.264 video as RTP packets over UDP. Supply the IPv4 address of the Archiver server and the destination UDP port used by the publisher. For example, a publisher sending to 192.168.1.10:5004 requires that address and port in the enrollment request.

public static Task<AddUnitResponse> EnrollRtpUnicastStreamAsync(
    Engine engine, Guid archiverRoleGuid, IPAddress archiverAddress, int destinationPort)
{
    VideoUnitProductInfo productInfo = engine.VideoUnitManager.FindProductsByManufacturer("Generic Stream")
        .FirstOrDefault(p => p.ProductType == "RTP Unicast Udp");

    if (productInfo == null)
        throw new InvalidOperationException("The Generic Stream RTP Unicast Udp product is not available.");

    var endpoint = new IPEndPoint(archiverAddress, destinationPort);
    var unitInfo = new AddVideoUnitInfo(productInfo, endpoint, useDefaultCredentials: false);
    unitInfo.SpecialFeatures["Codec"] = "H.264";

    return engine.VideoUnitManager.AddVideoUnit(unitInfo, archiverRoleGuid);
}

The publisher must send RTP packets to that address and port. Select RTP Unicast Udp (No ping) if ICMP checks are blocked. To use another codec, replace H.264 with its exact value from the table.

Enrolling an offline device

Select Offline device and Network share for an integration that supplies recorded files. Create the folder before enrollment. Grant the account running the Genetec Server service read and write access to the folder and its files, and permission to create subfolders and move or delete files. Supply a unit name that is unique across the Security Center system and any federated systems.

Warning

Successful imports delete the source files from the import folder. Keep original recordings elsewhere and place copies in this folder.

For example, use Loading bay imports with \\video-ingest\clips\loading-bay. The loopback endpoint identifies a device that uses a folder; it does not refer to a camera or a network share host.

public static Task<AddUnitResponse> EnrollOfflineDeviceAsync(
    Engine engine, Guid archiverRoleGuid, string unitName, string folderPath)
{
    VideoUnitProductInfo productInfo = engine.VideoUnitManager.FindProductsByManufacturer("Offline device")
        .FirstOrDefault(p => p.ProductType == "Network share");

    if (productInfo == null)
        throw new InvalidOperationException("The Offline device Network share product is not available.");

    var unitInfo = new AddVideoUnitInfo(productInfo, new IPEndPoint(IPAddress.Loopback, 0), useDefaultCredentials: false);
    unitInfo.SpecialFeatures["UnitName"] = unitName;
    unitInfo.SpecialFeatures["Path"] = folderPath;

    return engine.VideoUnitManager.AddVideoUnit(unitInfo, archiverRoleGuid);
}

The offline product uses UnitName and Path; the endpoint port is unused. Enrollment creates a camera for imported recordings. Configure retention and recording timestamps before placing files in the folder.

Variants

To attach the unit's cameras to a specific area on enrollment, use the AddVideoUnit(AddVideoUnitInfo, Guid archiverRole, Guid area) overload.

To remove a unit, call engine.VideoUnitManager.DeleteVideoUnit(Guid unitGuid, bool deleteVideoArchives). Setting deleteVideoArchives to false converts the unit's cameras into ghost cameras and preserves the recorded archives; setting it to true deletes them along with the unit. The Archiver role hosting the unit must be running for the deletion to take effect. You can observe completion through the UnitDeleted event.

See also

Platform SDK

Plugin SDK

Workspace SDK

Media SDK

Macro SDK

Web SDK

Synergis RIO

Media Gateway

Genetec Web Player

Clone this wiki locally