Skip to content

media sdk ptz coordinates manager

Andre Lafleur edited this page Oct 8, 2026 · 8 revisions

About PtzCoordinatesManager

PtzCoordinatesManager controls one PTZ (pan-tilt-zoom) camera. It sends movement, preset, pattern, tour, menu, auxiliary, and coordinate commands, and it raises events when the camera reports coordinates or when movement starts and stops.

For workflows that control more than one PTZ camera from a single object, use AggregatePtzCoordinatesManager, described below. The aggregate uses the same command arguments; every command method takes a camera GUID, and events carry the camera GUID so multi-tile UIs can route updates to the correct view.

How PTZ control works

PtzCoordinatesManager connects to a camera through a Platform SDK Engine and a camera GUID. After Initialize, the manager can send commands in these categories:

  • Discrete PTZ commands through ControlPtz(PtzCommandType, arg1, arg2).
  • Absolute or relative PTZ coordinates through SetCoordinates(PtzCoordinatesType, pan, tilt, zoom).
  • Normalized PTZ coordinates through SetNormalizedCoordinates(PtzNormalizedCoordinates).
  • View-space input through MovePtzToPoint and MovePtzToRect.

Coordinate updates are received through CoordinatesReceived and NormalizedCoordinatesReceived.

Check camera capabilities

Check PTZ capability on the Camera entity before sending commands. PtzCoordinatesManager.ControlPtz does not call Camera.PtzCapabilities.IsSupportedCommand for you.

Camera camera = engine.GetEntity(cameraGuid) as Camera;
if (camera == null || !camera.IsPtz)
{
    return;
}

IPtzCapabilities capabilities = camera.PtzCapabilities;
if (!capabilities.IsSupportedCommand(PtzCommandType.StartPanTilt))
{
    return;
}

Use the count and base properties when a command needs a preset, pattern, or preset-tour identifier.

if (capabilities.IsSupportedCommand(PtzCommandType.GoToPreset)
    && capabilities.NumberOfPresets > 0)
{
    int firstPreset = capabilities.PresetBase;
    int lastPreset = capabilities.PresetBase + capabilities.NumberOfPresets - 1;
    int preset = 4;
    if (preset < firstPreset || preset > lastPreset)
    {
        return;
    }

    manager.ControlPtz(PtzCommandType.GoToPreset, preset, 0);
}

Camera.PtzCapabilities returns IPtzCapabilities. The PtzCapabilities implementation also has auxiliary counts and coordinate range properties, such as AuxiliaryBase, NumberOfAuxiliaries, IsSphericalSpacePanSupported, SphericalSpaceMinimumPan, SphericalSpaceMaximumPan, IsZoomFactorSupported, ZoomFactorMinimum, and ZoomFactorMaximum.

if (camera.PtzCapabilities is PtzCapabilities details
    && details.IsZoomFactorSupported)
{
    double minimumZoom = details.ZoomFactorMinimum;
    double maximumZoom = details.ZoomFactorMaximum;
}

Create a manager

using Genetec.Sdk;
using Genetec.Sdk.Entities;
using Genetec.Sdk.Media.Ptz;

using PtzCoordinatesManager manager = new PtzCoordinatesManager();

manager.CoordinatesReceived += OnCoordinatesReceived;
manager.NormalizedCoordinatesReceived += OnNormalizedCoordinatesReceived;
manager.PtzStopped += OnPtzStopped;
manager.UnhandledException += OnPtzException;

manager.Initialize(engine, cameraGuid);

Initialize requires a connected Engine, and the Security Center license must include the Media SDK option. Initialize(engine, cameraGuid) calls the overload that accepts a client subnet with Guid.Empty.

Choose the client subnet

The clientSubnet parameter is the GUID of the Security Center network entity that represents the SDK application's network. Security Center uses that network's configuration to resolve the PTZ route. The camera can belong to a different network.

The two-argument Initialize overload uses Guid.Empty to select the client network automatically. When your application creates its own Engine and logs on to Security Center, selection uses the computer's IP addresses. If no configured network matches, it uses Default network.

When your code runs in a server-side plugin and uses the plugin's Engine, selection first uses the network assigned to the server hosting the plugin.

Passing the GUID of Default network selects that entity explicitly. It is different from requesting automatic selection with Guid.Empty.

Retrieve network GUIDs

Run this snippet from an asynchronous method after logon. It queries the configured networks and prints their names, GUIDs, default-network flags, and address prefixes.

var query = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
query.EntityTypeFilter.Add(EntityType.Network);
query.StrictResults = true;
query.PageSize = 1000;
query.Page = 1;

while (true)
{
    QueryCompletedEventArgs result = await Task.Factory.FromAsync(query.BeginQuery, query.EndQuery, null);

    foreach (DataRow row in result.Data.Rows.Cast<DataRow>().Take(query.PageSize))
    {
        var network = engine.GetEntity<Network>((Guid)row["Guid"]);

        Console.WriteLine($"{network.Name}: {network.Guid}");
        Console.WriteLine($"Default network: {network.IsDefaultNetwork}");
        Console.WriteLine($"IPv4 prefix: {network.IPv4AddressPrefix}, mask: {network.IPv4NetworkMask}");
        Console.WriteLine($"IPv6 prefix: {network.IPv6Prefix}/{network.IPv6PrefixLength}");
    }

    if (result.Data.Rows.Count <= query.PageSize)
        break;

    query.Page++;
}

The query can return one extra row to indicate that another page exists. Processing only PageSize rows from each page avoids listing that extra network twice.

Use IsDefaultNetwork to identify Default network. An unset IPv4 prefix or mask is displayed as 255.255.255.255; that value does not identify the default network.

Select and use the client network

  1. Compare the listed address prefixes with the SDK application's network addresses. For a computer with multiple interfaces or a virtual private network (VPN) connection, confirm the intended client network with the Security Center administrator.
  2. In Config Tool, open Network view, select that network, and examine its Properties and Routes. Confirm that the configuration represents the connections the application must use.
  3. Pass the selected network entity's GUID as the third argument to Initialize.

In this initialization snippet, networkGuid is the GUID selected from the query results:

manager.Initialize(engine, cameraGuid, clientSubnet: networkGuid);

Successful initialization does not confirm that the intended network was selected or that a PTZ command reached the camera. If commands have no effect, verify the client-network selection and routing configuration.

If PTZ works in Security Desk but not in your SDK application, compare their client-network selections, even when both run on the same workstation.

  1. In Security Desk, open Options > General and locate Network.
  2. Check whether Auto-detect or Specific is selected, and note the displayed network.
  3. Retrieve that Network entity's GUID using the preceding snippet and pass it explicitly to the SDK initialization overload.
  4. Repeat the preset command using the same Security Center user and camera.

The workstation's network options affect Security Desk and Config Tool for all users. Your external SDK application does not automatically inherit that selection. For the product procedure, find Customizing network options in the Genetec TechDoc Hub.

Use the same clientSubnet for MediaPlayer and PtzCoordinatesManager when playback and PTZ must resolve routes from the same client network. For AggregatePtzCoordinatesManager, pass the selected network GUID to Initialize(engine, clientSubnet) before adding cameras.

For network configuration, find Network - Properties tab and Adding networks in the Genetec TechDoc Hub. Select the guide for your installed Security Center version.

Choose the command method

Method Use it for
ControlPtz(PtzCommandType, arg1, arg2) Discrete commands whose arguments are plain integers, such as movement, presets, patterns, tours, auxiliaries, menu navigation, lock commands, and device-specific commands.
SetCoordinates(PtzCoordinatesType, pan, tilt, zoom) Absolute or relative pan/tilt/zoom coordinates. Use this instead of packing GoToAbsolutePosition or GoToRelativePosition arguments yourself.
SetNormalizedCoordinates(PtzNormalizedCoordinates) Normalized position values. Use this instead of calling ControlPtz(PtzCommandType.GoToNormalizedPosition, ...), because the normalized command needs an XML argument that ControlPtz does not accept.
MovePtzToPoint(Point center, Size viewSize) Click-to-center: move the camera so the picked view point becomes the center.
MovePtzToRect(Rect rect, Size viewSize) Box zoom: move and zoom so the picked view rectangle fills the camera view.

Movement commands

Continuous movement commands form start and stop pairs. Send the start command when input begins, and then send the matching stop command when input ends.

// Start panning right.
manager.ControlPtz(PtzCommandType.StartPanTilt, 50, 0);

// Stop pan and tilt when the button, key, or joystick input is released.
manager.ControlPtz(PtzCommandType.StopPanTilt, 0, 0);
// Start zooming in.
manager.ControlPtz(PtzCommandType.StartZoom, 0, 30);

// Stop zooming.
manager.ControlPtz(PtzCommandType.StopZoom, 0, 0);

Security Center UI code throttles repeated start commands before sending them to a camera. PtzCoordinatesManager does not add that throttling, so joystick-style or drag-style controls should avoid sending every pointer update directly.

Command arguments

arg1 and arg2 are interpreted by the command type. Check IsSupportedCommand before sending any command.

Command arg1 arg2
StartPanTilt Horizontal speed. Negative values pan left, positive values pan right, and 0 does not pan on that axis. Security Center UI and gateway paths use signed values in the -100 to 100 range. Vertical speed. Negative values tilt down, positive values tilt up, and 0 does not tilt on that axis. Security Center UI and gateway paths use signed values in the -100 to 100 range.
StopPanTilt 0 0
StartZoom 0 for zoom in, 1 for zoom out. Speed. Security Center UI and gateway paths use values up to 100.
StopZoom 0 0
StartFocus 0 for near focus, 1 for far focus. Speed.
StopFocus 0 0
StartIris 0 to open the iris, 1 to close the iris. Speed.
StopIris 0 0
GoToPreset, SetPreset, ClearPreset Preset ID. Use PresetBase and NumberOfPresets to calculate the valid range. 0
StartPattern, StopPattern, RunPattern, ClearPattern Pattern ID. Use PatternBase and NumberOfPatterns to calculate the valid range. 0
StartPresetTour, StopPresetTour Preset-tour ID. Use PresetTourBase and NumberOfPresetTours to calculate the valid range. 0
SetAuxiliary, ClearAuxiliary Auxiliary ID. If the capability object is PtzCapabilities, use AuxiliaryBase and NumberOfAuxiliaries to calculate the valid range. 0
Home, Flip, Enter 0 0
Menu commands 0, unless the device integration documents a command-specific value. 0, unless the device integration documents a command-specific value.
SetPositionZero 1 restores the default zero position. 0 uses the current position as zero. 0
Lock, OverrideLock 0 0
GoToAbsolutePosition, GoToRelativePosition Packed coordinate argument. Use SetCoordinates instead. Packed coordinate argument. Use SetCoordinates instead.
GoToNormalizedPosition 0 when sent through SetNormalizedCoordinates. 0 when sent through SetNormalizedCoordinates.
GoToImagePosition Packed image-position argument. Use MovePtzToPoint or MovePtzToRect instead. Packed image-position argument. Use MovePtzToPoint or MovePtzToRect instead.
SpecificCommand, VCR commands, Kalatel commands, GoToPosition, RunTour, RunSequence Device-specific value. Device-specific value.

ControlPtz has no third argument. Commands that require a string payload, such as the normalized-position XML payload, must use a helper method that builds that payload internally.

PtzCommandType groups

PtzCommandType contains common commands and device-specific commands. Support is per camera.

Group Command values
Do not send InvalidCommand, LastCommand
Continuous movement StartZoom, StopZoom, StartPanTilt, StopPanTilt, StartIris, StopIris, StartFocus, StopFocus
Presets GoToPreset, SetPreset, ClearPreset
Patterns StartPattern, StopPattern, RunPattern, ClearPattern
Preset tours StartPresetTour, StopPresetTour
Position commands GoToPosition, GoToAbsolutePosition, GoToRelativePosition, GoToNormalizedPosition, GoToImagePosition, GetPosition, SetPositionZero
Basic actions Flip, Enter, Home, Lock, OverrideLock
Menu commands MenuOn, MenuOff, MenuUp, MenuDown, MenuLeft, MenuRight, MenuNext, MenuPrevious, MenuStop, MenuCancel, MenuTextMode, MenuUpUp, MenuDownUp, MenuLeftUp, MenuRightUp, MenuUpDown, MenuDownDown, MenuLeftDown, MenuRightDown, MenuBank, MenuStart, MenuNumber, MenuExit, MenuScrollLeft, MenuScrollRight, MenuScrollUp, MenuScrollDown
Auxiliary commands SetAuxiliary, ClearAuxiliary
VCR or media-transport commands Vcr, Eject, Stop, Record, Pause, Play, Rewind, Fastfoward, NextFrame, PrevKeyFrame
Device-specific commands SpecificCommand, RunTour, RunSequence, Alarm, Sequence, Clear, Set, First

Use CoordinatesReceived or NormalizedCoordinatesReceived to receive camera position updates. GetPosition exists in the enum, but the coordinate manager is already initialized to request coordinate updates.

Absolute and relative coordinates

Use SetCoordinates for GoToAbsolutePosition and GoToRelativePosition.

manager.SetCoordinates(
    PtzCoordinatesType.Absolute,
    pan: 45.25,
    tilt: -10.0,
    zoom: 2.0);
manager.SetCoordinates(
    PtzCoordinatesType.Relative,
    pan: 5.0,
    tilt: 0.0,
    zoom: 1.0);

For absolute coordinates, pan and tilt must be in the -360.00 to 360.00 range, and zoom must be greater than or equal to 1.0000.

For relative coordinates, pan and tilt use the same -360.00 to 360.00 range. The relative-coordinate builder encodes zoom, but it does not apply the absolute zoom minimum check.

The coordinate helper packs pan, tilt, and zoom into the integer arguments expected by the PTZ command. Pan and tilt are packed at two decimal places of precision, and zoom is packed at four decimal places of precision.

Normalized coordinates

PtzNormalizedCoordinates is a sparse container. Set only the coordinate values you want to send.

var coordinates = new PtzNormalizedCoordinates
{
    SphericalSpacePanValue = 30.0,
    SphericalSpaceTiltValue = -5.0,
    ZoomFactorValue = 4.0
};

manager.SetNormalizedCoordinates(coordinates);

Supported keys are:

  • SphericalSpacePan
  • SphericalSpaceTilt
  • ZoomFactor
  • UnknownSpacePan
  • UnknownSpaceTilt
  • UnknownSpaceZoom

Spherical-space pan and tilt values are in degrees. ZoomFactorValue is a magnification factor, such as 1.0 or 32.0. Unknown-space values use device-specific units.

Use ContainsSphericalSpacePanValue, ContainsSphericalSpaceTiltValue, ContainsZoomFactorValue, the other Contains... properties, ContainsKey, or TryGetValue before reading values that the camera might not provide. The typed double getters return double.NaN when the value is missing or cannot be parsed. The string indexer throws if the key is missing.

SetNormalizedCoordinates serializes the populated keys into a PtzNormalizedPosition XML payload and sends it with GoToNormalizedPosition. PtzNormalizedCoordinates does not validate the values against the camera ranges. Use the range properties on PtzCapabilities when they are available.

View-space commands

MovePtzToPoint and MovePtzToRect convert WPF view coordinates into the GoToImagePosition command.

Point mousePosition = Mouse.GetPosition(videoView);
Size viewSize = new Size(videoView.ActualWidth, videoView.ActualHeight);

manager.MovePtzToPoint(mousePosition, viewSize);
Rect selectedRectangle = new Rect(x, y, width, height);
Size viewSize = new Size(videoView.ActualWidth, videoView.ActualHeight);

manager.MovePtzToRect(selectedRectangle, viewSize);

View-space coordinates use the top-left corner as the origin. The conversion divides the point or rectangle by viewSize, so (0, 0) maps to the top-left of the image and (1, 1) maps to the bottom-right after normalization.

Pass the current size of the view that produced the input. If the view resizes between mouse down and mouse up, calculate the rectangle against the current view size before calling the manager.

MovePtzToPoint rejects negative X or Y values. MovePtzToRect rejects negative X, Y, Width, or Height values. The manager does not clamp points or rectangles to the view bounds, and it does not check for a zero viewSize; keep the input inside the video view and pass a non-zero size.

For click-to-center, the helper sends a point-sized rectangle and uses a zoom value of 1.0. For box zoom, the helper centers on the rectangle and uses the inverse of the rectangle width ratio as the zoom value.

Permissions and errors

The PTZ send path checks the Security Center privilege associated with the command before sending it to the camera.

Commands Required privilege
StartZoom, StopZoom, StartPanTilt, StopPanTilt, Flip, Home, GoToAbsolutePosition, GoToRelativePosition, GoToNormalizedPosition, GoToImagePosition BasicPtzOperations
GoToPreset UsePtzPresets
SetPreset, ClearPreset EditPtzPreset
StartIris, StopIris, StartFocus, StopFocus ChangeFocusAndIris
SetAuxiliary, ClearAuxiliary UsePtzAuxiliaries
RunPattern, StartPresetTour, StopPresetTour UsePtzPatterns
StartPattern, StopPattern, ClearPattern SetPtzPattern
Lock, OverrideLock LockPtz before the command is sent. The override path may apply additional checks after this privilege passes, and an override request can still be rejected at that later stage.
GetPosition No privilege is associated by the PTZ command mapping. Use coordinate events for position updates.
All other valid command values UseSpecificCommands

Do not send InvalidCommand or LastCommand.

Common validation and error behavior:

  • Calling command methods before Initialize, or after the engine is disconnected, throws InvalidOperationException.
  • Initialize throws if the engine is null, not connected, or does not have Media SDK access.
  • Passing an undefined PtzCommandType value throws InvalidOperationException.
  • SetCoordinates throws ArgumentOutOfRangeException for pan, tilt, or absolute zoom values outside the accepted ranges.
  • MovePtzToPoint and MovePtzToRect throw ArgumentOutOfRangeException for negative view-space values.
  • SetUserId throws when the user GUID is empty, does not identify a User entity, or identifies a user with a higher security level than the logged-on SDK user.
  • Subscribe to UnhandledException for asynchronous PTZ failures, and read ErrorDetails when it is not null.

Events

Event Args When it is raised
CoordinatesReceived PtzCoordinatesEventArgs The camera reported non-normalized coordinates.
NormalizedCoordinatesReceived PtzNormalizedCoordinatesEventArgs The camera reported normalized coordinates.
PtzStarted PtzCoordinatesEventArgs Non-normalized PTZ movement started.
PtzStopped PtzCoordinatesEventArgs Non-normalized PTZ movement stopped.
NormalizedPtzStarted PtzNormalizedCoordinatesEventArgs Normalized PTZ movement started.
NormalizedPtzStopped PtzNormalizedCoordinatesEventArgs Normalized PTZ movement stopped.
UnhandledException UnhandledExceptionEventArgs A PTZ operation raised an unhandled exception.

PtzCoordinatesEventArgs.Coordinates returns a PtzCoordinates object with read-only Pan, Tilt, and Zoom values and a CoordinatesType value that indicates whether the coordinates are absolute or relative. PtzNormalizedCoordinatesEventArgs.Coordinates returns a PtzNormalizedCoordinates object; read it with the Contains... properties and typed getters described in Normalized coordinates.

PtzStarted and PtzStopped are based on coordinate changes. A movement is considered started when new coordinates differ from the previous coordinates after the manager was stopped. A movement is considered stopped when two consecutive coordinate updates are equal while the manager was moving.

SetUserId

SetUserId(Guid userId) runs subsequent PTZ commands under a specific Security Center user identity. Leave it unset when the logged-on SDK user is the right command context.

The selected user must:

  • Not be Guid.Empty.
  • Resolve to a User entity.
  • Not have a higher security level than the logged-on SDK user.

AggregatePtzCoordinatesManager

AggregatePtzCoordinatesManager uses a single manager instance to control PTZ for each camera added to it. It exposes the same command methods as PtzCoordinatesManager, but every command method takes a camera GUID as the first argument, and the coordinate and movement events carry the camera GUID. The UnhandledException event does not identify a camera.

using AggregatePtzCoordinatesManager aggregate =
    new AggregatePtzCoordinatesManager();

aggregate.CoordinatesReceived += OnAggregateCoordinates;
aggregate.Initialize(engine);

await aggregate.AddCameraAsync(cameraGuid);

aggregate.ControlPtz(
    cameraGuid,
    PtzCommandType.GoToPreset,
    arg1: 4,
    arg2: 0);

aggregate.RemoveCamera(new List<Guid> { cameraGuid });

Initialize must be called once. It requires a connected Engine, and the Security Center license must include the Media SDK option. The overload that accepts clientSubnet uses the route behavior described in Choose the client subnet.

Aggregate-only method Description
AddCameraAsync(Guid cameraGuid) Adds one camera. The returned task completes after the camera connection task completes.
AddCameraAsync(List<Guid> cameraGuids) Adds several cameras and returns true after all connection tasks complete. The return value is not a per-camera result.
RemoveCamera(List<Guid> cameraGuids) Removes one or more cameras.

Wait for AddCameraAsync before sending commands. ControlPtz returns void, so a command sent before the camera connection is established produces no return-value signal. While a camera connection is pending, only RunPattern, GoToPreset, SetAuxiliary, and ClearAuxiliary are queued and replayed once the camera connects; every other command type is dropped until the camera is connected.

Sending a command for a camera that was never added throws ArgumentException.

Aggregate events use aggregate event-arg types that carry the camera GUID alongside the coordinate data: AggregatePtzCoordinatesEventArgs, AggregatePtzNormalizedCoordinatesEventArgs, and the corresponding started/stopped variants.

Disposing

Both PTZ managers implement IDisposable. Dispose the manager when the workflow ends. Dispose the existing manager before switching a single-camera UI from one selected camera to another.

using PtzCoordinatesManager manager = new PtzCoordinatesManager();
manager.Initialize(engine, cameraGuid);

See also

  • About MediaPlayer: MediaPlayer WPF control for live, recorded, and local-file playback.

Platform SDK

Plugin SDK

Workspace SDK

Media SDK

Macro SDK

Web SDK

Synergis RIO

Media Gateway

Genetec Web Player

Clone this wiki locally