Repository navigation
media sdk ptz coordinates manager
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.
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
MovePtzToPointandMovePtzToRect.
Coordinate updates are received through CoordinatesReceived and NormalizedCoordinatesReceived.
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;
}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.
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.
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.
- 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.
- 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.
- 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.
- In Security Desk, open Options > General and locate Network.
- Check whether Auto-detect or Specific is selected, and note the displayed network.
- Retrieve that Network entity's GUID using the preceding snippet and pass it explicitly to the SDK initialization overload.
- 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.
| 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. |
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.
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 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.
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.
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:
SphericalSpacePanSphericalSpaceTiltZoomFactorUnknownSpacePanUnknownSpaceTiltUnknownSpaceZoom
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.
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.
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, throwsInvalidOperationException. -
Initializethrows if the engine is null, not connected, or does not have Media SDK access. - Passing an undefined
PtzCommandTypevalue throwsInvalidOperationException. -
SetCoordinatesthrowsArgumentOutOfRangeExceptionfor pan, tilt, or absolute zoom values outside the accepted ranges. -
MovePtzToPointandMovePtzToRectthrowArgumentOutOfRangeExceptionfor negative view-space values. -
SetUserIdthrows when the user GUID is empty, does not identify aUserentity, or identifies a user with a higher security level than the logged-on SDK user. - Subscribe to
UnhandledExceptionfor asynchronous PTZ failures, and readErrorDetailswhen it is not null.
| 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(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
Userentity. - Not have a higher security level than the logged-on SDK user.
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.
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);- About MediaPlayer: MediaPlayer WPF control for live, recorded, and local-file playback.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- ASP.NET hosting
- SDK compatibility
- Migrating to modern .NET
- Entities
- Entity cache
- Entity loading, cache, and query options
- Detecting entity changes
- Entity change event reference
- Transactions
- Security Center events
- Actions
- Security Desk
- Custom events
- Event-to-actions
- Managing macros
- ReportManager
- ReportManager query reference
- Access control raw events
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Entity write restrictions
- About custom fields
- About video
- About cameras
- Enrolling a video unit
- Ingesting third-party video
- Archiver and auxiliary archiver roles
- Archive transfer
- About access control
- About cardholders and credentials
- About doors, areas, elevators, and access points
- About access rules and schedules
- About access control units and interface modules
- Enrolling an access control unit
- Door templates
- Visitors
- Mobile credentials
- About threat levels
- About alarms
- About incidents
- Maps
- Logging
- Overview
- Localization
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Engine extensions
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- Modern .NET support
- Overview
- Localization
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual actions
- Custom actions
- Options extensions
- Configuration pages
- Monitors
- Shared components
- Commands
- Extending events
- Map extensions
- Timeline providers
- Image extractors
- Credential encoders
- Credential readers
- Cardholder fields extractors
- Badge printers
- Content builders
- Dashboard widgets
- Incidents
- Logon providers
- Pinnable content builders
- Custom report pages
- Overview
- Getting started
- Media file formats
- MediaPlayer
- VideoSourceFilter
- MediaExporter
- MediaFile
- G64 converters
- FileCryptingManager
- PlaybackSequenceQuerier
- PlaybackStreamReader
- OverlayFactory
- PtzCoordinatesManager
- AudioTransmitter
- AudioRecorder
- AnalogMonitorController
- Camera blocking
- Overview
- Getting started
- Referencing entities
- Entity operations
- About access control in the Web SDK
- About video in the Web SDK
- Users and user groups
- Partitions
- Custom fields
- Custom card formats
- Actions
- Events and alarms
- Incidents
- Reports
- Tasks
- Macros
- Custom entity types
- System endpoints
- Performance guide
- Reference
- Endpoints
- Constants
- Enumerations
- Under the hood
- Troubleshooting