Skip to content

platform sdk entities

Andre Lafleur edited this page Dec 11, 2025 · 1 revision

About entities

Entities are the fundamental building blocks in Security Center that represent all physical and logical objects. Every component in your system, from cameras and doors to users and access rules, is represented as an entity.

Entity base class architecture

All entities in the SDK inherit from the abstract Entity base class, creating a unified object model:

// Entity is the abstract base class
public abstract class Entity
{
    public Guid Guid { get; }
    public int? LogicalId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime CreatedOn { get; }
    public EntityType EntityType { get; }
    // ... other common properties
}

// Specific entity types inherit from Entity
public class Camera : Entity { /* Camera-specific properties */ }
public class Cardholder : Entity { /* Cardholder-specific properties */ }
public class Door : Entity { /* Door-specific properties */ }
public class AccessRule : Entity { /* AccessRule-specific properties */ }

Working with entity inheritance

Since all entities inherit from the base Entity class, you can work with them polymorphically:

// Generic entity handling
Entity someEntity = engine.GetEntity(entityGuid);
Console.WriteLine($"Entity: {someEntity.Name} (Type: {someEntity.EntityType})");

// Casting to specific types when you need type-specific properties
if (someEntity is Camera camera)
{
    // Access camera-specific properties
    Console.WriteLine($"Camera IP: {camera.IpAddress}");
}
else if (someEntity is Cardholder cardholder)
{
    // Access cardholder-specific properties
    Console.WriteLine($"Cardholder: {cardholder.FirstName} {cardholder.LastName}");
}

// Direct casting when you know the type
Camera camera = (Camera)engine.GetEntity(cameraGuid);
Camera camera = engine.GetEntity<Camera>(cameraGuid);

Cardholder cardholder = (Cardholder)engine.GetEntity(cardholderGuid);
Cardholder cardholder = engine.GetEntity<Cardholder>(cardholderGuid);

Common entity properties

All entities share common properties inherited from the base Entity class:

  • Name: User-friendly display name (not unique - multiple entities can have the same name)
  • Description: Optional detailed description
  • GUID: Globally unique identifier (explained below)
  • LogicalId: System-specific numeric identifier (explained below)
  • CreatedOn: When the entity was created
  • EntityType: Enumeration indicating the specific entity type

Key characteristics

Unified Architecture: All entities share common properties and behaviors through inheritance, providing consistency across different types of objects.

Persistent Objects: Entities exist in the Directory Server database.

Real-time Updates: Changes to entities are automatically synchronized across all connected clients.

Hierarchical Organization: Entities can have parent-child relationships, enabling logical grouping.

Entity Types

The SDK supports numerous entity types, each serving specific purposes in your security system.

Common Entity Types

  • EntityType.Camera - Video surveillance devices
  • EntityType.Door - Physical access points
  • EntityType.Area - Geographic or logical zones
  • EntityType.Zone - Security areas with specific rules
  • EntityType.Cardholder - People with system access
  • EntityType.Credential - Access cards, badges, or mobile credentials
  • EntityType.AccessRule - Permissions defining who can access what
  • EntityType.Schedule - Time-based access definitions
  • EntityType.Partition - Logical groupings for organization
  • EntityType.User - System users (administrators, operators)
  • EntityType.UserGroup - Collections of users with similar roles
  • EntityType.CustomEntity - Your custom entity types

Entity Identifiers

Every entity in Security Center has two distinct identifiers that serve different purposes in system integration and management.

GUID (Globally Unique Identifier)

The GUID is a 128-bit unique identifier that guarantees uniqueness across all Security Center systems.

Key characteristics of GUIDs:

  • Globally unique: No two entities will ever have the same GUID, even across different Security Center installations
  • Persistent: The GUID never changes for the lifetime of the entity
  • Cross-system safe: You can safely reference entities by GUID across different Security Center systems
  • Database primary key: Used internally as the primary identifier in the Directory Server database
// Every entity has a GUID
Camera camera = engine.GetEntity<Camera>(cameraGuid);
Console.WriteLine($"Camera GUID: {camera.Guid}");

// GUIDs are unique across all Security Center systems
Guid cameraGuid = new Guid("12345678-1234-1234-1234-123456789ABC");
// This GUID will never exist on any other Security Center system

// Use GUID for reliable entity references
var myEntityReferences = new Dictionary<Guid, string>
{
    { camera.Guid, "Main entrance camera" },
    { cardholder.Guid, "John Doe employee record" }
};

Logical ID

The Logical ID is a unique identifier that you can assign to entities to help reference them more easily. Logical IDs are local to your system and do not change the entity's default system-generated ID (GUID). You can use Logical IDs to quickly find entities.

Key characteristics of Logical IDs:

  • System-specific: Only unique within a single Security Center system
  • Type-specific: Camera Logical ID 100 is different from Door Logical ID 100
  • Optional and manually assigned: Can only be set through the Config Tool or the SDK
  • Nullable: May be null if not manually assigned
  • Human-readable: Numeric values that are easier to work with than GUIDs
  • Can be reused: When an entity is deleted, its Logical ID may be reused for new entities of the same type
// Logical ID is nullable and may be null if not manually assigned
Camera camera = engine.GetEntity<Camera>(cameraGuid);
Door door = engine.GetEntity<Door>(doorGuid);

Console.WriteLine($"Camera Logical ID: {camera.LogicalId?.ToString() ?? "Not assigned"}");
Console.WriteLine($"Door Logical ID: {door.LogicalId?.ToString() ?? "Not assigned"}");

// Logical IDs are type-specific within the same system
if (camera.LogicalId.HasValue)
{
    Camera cameraByLogicalId = engine.GetEntity(EntityType.Camera, camera.LogicalId.Value);
}

// Use Logical ID for human-friendly references when available
if (camera.LogicalId.HasValue)
{
    Console.WriteLine($"Processing Camera #{camera.LogicalId}: {camera.Name}");
}
else
{
    Console.WriteLine($"Processing Camera: {camera.Name} (No Logical ID assigned)");
}

var accessRule = engine.GetEntity<AccessRule>(accessRuleGuid);
accessRule.Doors.Add(doorGuid); // Use GUID for relationships

// Logical ID for user display when available
if (door.LogicalId.HasValue)
{
    Console.WriteLine($"Door #{door.LogicalId} - {door.Name}"); // User-friendly display
}

Searching and Querying Entities

To work with entities, you need to query them from the Directory Server using EntityConfigurationQuery and its specialized subtypes.

Understanding Query Results

All EntityConfigurationQuery and its specialized subtypes return query results in a standard format:

  • The query returns a DataTable with a single "Guid" column
  • Each row contains the GUID of an entity that matches your query filters
  • You then use these GUIDs with engine.GetEntity() to retrieve the actual entity objects

Understanding Filter Behavior

Important: All filters on queries are combined using AND logic, not OR logic.

When you set multiple filters on a query, entities must match all the specified criteria to be included in the results:

var cardholderQuery = (CardholderConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.CardholderConfiguration);

// These filters are combined with AND logic
cardholderQuery.FirstName = "John";                          // AND
cardholderQuery.LastName = "Smith";                         // AND
cardholderQuery.AccessStatus.Add(CardholderState.Active);   // AND
cardholderQuery.VisitorsOnly = false;                       // AND

// Result: Only cardholders where ALL conditions are true:
// FirstName = "John" AND LastName = "Smith" AND Status = Active AND VisitorsOnly = false

Examples of AND behavior:

// This finds cameras that have BOTH conditions
var cameraQuery = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
cameraQuery.EntityTypeFilter.Add(EntityType.Camera);
cameraQuery.Name = "Lobby";           // Name contains "Lobby" AND
cameraQuery.Description = "Main";     // Description contains "Main"
// Result: Only cameras where name contains "Lobby" AND description contains "Main"

// This finds entities of multiple types (this IS an OR for entity types)
cameraQuery.EntityTypeFilter.Add(EntityType.Camera);  // EntityType = Camera OR
cameraQuery.EntityTypeFilter.Add(EntityType.Door);    // EntityType = Door
// Exception: EntityTypeFilter collection acts as OR - entities can be Camera OR Door

Note: The EntityTypeFilter collection is the exception - adding multiple entity types creates an OR condition for entity types, but all other filters remain AND conditions.

Query Type Capabilities

EntityConfigurationQuery: Can query any entity types but offers only basic filtering options.

Specialized Query Types: Can only query their specific entity type but provide advanced, type-specific filters.

  • CardholderConfigurationQuery - Only queries cardholders
  • CredentialConfigurationQuery - Only queries credentials
  • UserConfigurationQuery - Only queries users
  • UserGroupConfigurationQuery - Only queries user groups
  • AccessRuleConfigurationQuery - Only queries access rules

Entity Query

The EntityConfigurationQuery class is use for querying entities:

Available Filters

Filter Type Description
EntityTypeFilter EntityTypeCollection Entity types to include (OR logic between types)
Name string Filter by entity name
NameSearchMode StringSearchMode How to match the name (Contains, StartsWith, Is)
Description string Filter by entity description
DescriptionSearchMode StringSearchMode How to match the description
EntityGuids Collection<Guid> Load specific entities by GUID
CustomEntityTypes Collection<Guid> Filter custom entities by their type GUID
LogicalId int? Filter by logical ID
Owner Guid Filter by owner
MaximumResultCount int Limit total number of results
Page int Page number for pagination (starts at 1)
PageSize int Number of results per page
GuidsOnly bool Return only GUIDs without loading entity data
DownloadAllRelatedData bool Download all related data for returned entities (may include non-matching entities in results)
DownloadCustomFields bool Include custom field data
StrictResults bool When true, results contain only entities matching the query criteria (use with DownloadAllRelatedData)
async IAsyncEnumerable<Camera> QueryCameras()
{
    var query = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
    query.EntityTypeFilter.Add(EntityType.Camera);
    query.Page = 1; // First page is 1
    query.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(query.BeginQuery, query.EndQuery, null);
        
        // Query returns GUIDs, convert to actual Camera entities
        var pageCameras = args.Data.AsEnumerable()
            .Take(query.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<Camera>();
            
        foreach (var camera in pageCameras)
        {
            yield return camera;
        }
        
        query.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > query.PageSize); // More pages if we got pageSize + 1 results
}

Querying Multiple Entity Types

// Always use pagination for multiple entity types - can return many entities
async IAsyncEnumerable<Entity> QueryMultipleTypes()
{
    var query = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
    query.EntityTypeFilter.Add(EntityType.Camera);
    query.EntityTypeFilter.Add(EntityType.Door);
    query.EntityTypeFilter.Add(EntityType.Area);
    query.Page = 1; // First page is 1
    query.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(query.BeginQuery, query.EndQuery, null);
        
        var pageEntities = args.Data.AsEnumerable()
            .Take(query.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))));
            
        foreach (var entity in pageEntities)
        {
            yield return entity;
        }
        
        query.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > query.PageSize); // More pages if we got pageSize + 1 results
}

Entity-Specific Query Types

Use entity-specific query types that provide additional filters beyond the basic EntityConfigurationQuery:

CardholderConfigurationQuery

Query for cardholder entities with filters for names, access status, visitor filtering, and time-based criteria.

Filters:

Filter Type Description
FirstName string Filter by first name
FirstNameSearchMode StringSearchMode How to match first name
FirstNameOrder OrderByType Sort order for first name
LastName string Filter by last name
LastNameSearchMode StringSearchMode How to match last name
LastNameOrder OrderByType Sort order for last name
FullName string Filter by full name
FullNameSearchMode StringSearchMode How to match full name
Email string Filter by email address
EmailSearchMode StringSearchMode How to match email
MobilePhoneNumber string Filter by mobile phone number
MobilePhoneNumberSearchMode StringSearchMode How to match phone number
AccessStatus Collection<CardholderState> Filter by access status (Active, Expired, Inactive)
CardholderGroupIds List<Guid> Filter by cardholder group membership
ActivationTimeRange TimeRange Filter by activation time range
ExpirationTimeRange TimeRange Filter by expiration time range
VisitorsOnly bool? Filter visitors only (true/false/null for both)
EntitySharingCriteria EntitySharingCriteria Entity sharing filters
async IAsyncEnumerable<Cardholder> FindCardholdersByName(string firstName)
{
    var cardholderQuery = (CardholderConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.CardholderConfiguration);
    
    // Cardholder-specific filters
    cardholderQuery.FirstName = firstName;
    cardholderQuery.FirstNameSearchMode = StringSearchMode.StartsWith;
    cardholderQuery.AccessStatus.Add(CardholderState.Active);
    cardholderQuery.VisitorsOnly = false; // Only regular cardholders
    cardholderQuery.Page = 1; // First page is 1
    cardholderQuery.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(cardholderQuery.BeginQuery, cardholderQuery.EndQuery, null);
        
        var pageCardholders = args.Data.AsEnumerable()
            .Take(cardholderQuery.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<Cardholder>();
            
        foreach (var cardholder in pageCardholders)
        {
            yield return cardholder;
        }
        
        cardholderQuery.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > cardholderQuery.PageSize); // More pages if we got pageSize + 1 results
}

CredentialConfigurationQuery

Query for credential entities with filters for assignment status, mobile credentials, and format types.

Filters:

Filter Type Description
FormatType List<Guid> Filter by credential format type GUIDs
UnassignedOnly bool Show only unassigned credentials
MobileCredentialOnly bool? Filter mobile credentials only
UniqueIds CredentialUniqueIdCollection Filter by specific credential unique IDs
async IAsyncEnumerable<Credential> FindUnassignedCredentials()
{
    var credentialQuery = (CredentialConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.CredentialConfiguration);
    
    // Credential-specific options
    credentialQuery.UnassignedOnly = true; // Only unassigned credentials
    credentialQuery.MobileCredentialOnly = false;
    credentialQuery.Page = 1; // First page is 1
    credentialQuery.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(credentialQuery.BeginQuery, credentialQuery.EndQuery, null);
        
        var pageCredentials = args.Data.AsEnumerable()
            .Take(credentialQuery.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<Credential>();
            
        foreach (var credential in pageCredentials)
        {
            yield return credential;
        }
        
        credentialQuery.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > credentialQuery.PageSize); // More pages if we got pageSize + 1 results
}

UserConfigurationQuery

Query for user entities with filters for names, email, status, and security levels.

Filters:

Filter Type Description
FirstName string Filter by first name
FirstNameSearchMode StringSearchMode How to match first name
FirstNameOrder OrderByType Sort order for first name
LastName string Filter by last name
LastNameSearchMode StringSearchMode How to match last name
LastNameOrder OrderByType Sort order for last name
Email string Filter by email address
EmailSearchMode StringSearchMode How to match email
Status Collection<UserStatus> Filter by user status (Activated, Deactivated)
UserGroupIds List<Guid> Filter by user group membership
SecurityLevelLowerBound int Lower bound for security level range
SecurityLevelLowerBoundOperator FieldRangeType Operator for lower bound
SecurityLevelUpperBound int Upper bound for security level range
SecurityLevelUpperBoundOperator FieldRangeType Operator for upper bound
GroupRecursive bool Include nested group memberships
EntitySharingCriteria EntitySharingCriteria Entity sharing filters
async IAsyncEnumerable<User> FindActiveUsers()
{
    var userQuery = (UserConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.UserConfiguration);
    
    // User-specific filters
    userQuery.Status.Add(UserStatus.Activated);
    userQuery.GroupRecursive = true; // Include nested groups
    userQuery.Page = 1; // First page is 1
    userQuery.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(userQuery.BeginQuery, userQuery.EndQuery, null);
        
        var pageUsers = args.Data.AsEnumerable()
            .Take(userQuery.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<User>();
            
        foreach (var user in pageUsers)
            yield return user;
            
        userQuery.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > userQuery.PageSize); // More pages if we got pageSize + 1 results
}

UserGroupConfigurationQuery

Query for user group entities with filters for email, status, and security levels.

Filters:

Filter Type Description
Email string Filter by email address
EmailSearchMode StringSearchMode How to match email
Status Collection<UserStatus> Filter by user status
UserGroupIds List<Guid> Filter by user group membership
SecurityLevelLowerBound int Lower bound for security level range
SecurityLevelLowerBoundOperator FieldRangeType Operator for lower bound
SecurityLevelUpperBound int Upper bound for security level range
SecurityLevelUpperBoundOperator FieldRangeType Operator for upper bound
GroupRecursive bool Include nested group memberships
EntitySharingCriteria EntitySharingCriteria Entity sharing filters
async IAsyncEnumerable<UserGroup> FindUserGroups()
{
    var userGroupQuery = (UserGroupConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.UserGroupConfiguration);
    
    // User group-specific filters
    userGroupQuery.GroupRecursive = true;
    userGroupQuery.Page = 1; // First page is 1
    userGroupQuery.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(userGroupQuery.BeginQuery, userGroupQuery.EndQuery, null);
        
        var pageUserGroups = args.Data.AsEnumerable()
            .Take(userGroupQuery.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<UserGroup>();
            
        foreach (var userGroup in pageUserGroups)
            yield return userGroup;
            
        userGroupQuery.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > userGroupQuery.PageSize); // More pages if we got pageSize + 1 results
}

AccessRuleConfigurationQuery

Query for access rule entities with filters for rule types.

Filters:

Filter Type Description
AccessRuleType AccessRuleType Filter by access rule type
async IAsyncEnumerable<AccessRule> FindAccessRulesByType(AccessRuleType ruleType)
{
    var accessRuleQuery = (AccessRuleConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.AccessRuleConfiguration);
    
    // Access rule-specific filters
    accessRuleQuery.AccessRuleType = ruleType;
    accessRuleQuery.Page = 1; // First page is 1
    accessRuleQuery.PageSize = 1000;
    
    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(accessRuleQuery.BeginQuery, accessRuleQuery.EndQuery, null);
        
        var pageAccessRules = args.Data.AsEnumerable()
            .Take(accessRuleQuery.PageSize) // Exclude the +1 item used for pagination detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<AccessRule>();
            
        foreach (var accessRule in pageAccessRules)
            yield return accessRule;
            
        accessRuleQuery.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > accessRuleQuery.PageSize); // More pages if we got pageSize + 1 results
}

Pagination for Large Datasets

For large datasets, use pagination with IAsyncEnumerable<T> for memory-efficient processing:

Understanding Pagination Behavior

When using pagination, Security Center returns pageSize + 1 results if more pages are available:

  • The extra item (+1) is the first entity of the next page
  • This helps detect if more pages exist without making additional queries
  • Use .Take(query.PageSize) to exclude this extra item from your results
// Streaming entities with IAsyncEnumerable for memory efficiency
async IAsyncEnumerable<Cardholder> QueryAllCardholders()
{
    var query = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
    query.EntityTypeFilter.Add(EntityType.Cardholder);
    query.Page = 1; // First page is 1
    query.PageSize = 1000;

    QueryCompletedEventArgs args;
    do
    {
        args = await Task.Factory.FromAsync(query.BeginQuery, query.EndQuery, null);
        
        // Process entities from current page
        var pageCardholders = args.Data.AsEnumerable()
            .Take(query.PageSize) // Exclude the +1 item used for next page detection
            .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
            .OfType<Cardholder>();
            
        // Yield each entity individually for streaming processing
        foreach (var cardholder in pageCardholders)
            yield return cardholder;
        
        query.Page++; // Move to next page
        
    } while (args.Data.Rows.Count > query.PageSize); // More pages if we got pageSize + 1 results
}

// Usage example:
async Task ProcessAllCardholders()
{
    await foreach (var cardholder in QueryAllCardholders())
    {
        Console.WriteLine($"Processing: {cardholder.FirstName} {cardholder.LastName}");
        // Process one cardholder at a time without loading all into memory
    }
}

Query Without Pagination

async Task<Camera> FindCameraByName(string exactName)
{
    var query = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
    query.EntityTypeFilter.Add(EntityType.Camera);
    query.Name = exactName; 
    query.NameSearchMode = StringSearchMode.Is;
    query.MaximumResultCount = 1;
    
    QueryCompletedEventArgs args = await Task.Factory.FromAsync(query.BeginQuery, query.EndQuery, null);
    
    return args.Data.AsEnumerable()
        .Select(row => engine.GetEntity(row.Field<Guid>(nameof(Guid))))
        .OfType<Camera>()
        .FirstOrDefault();
}

Retrieving Entities

Once you have entity GUIDs (from queries or other sources), you can retrieve the actual entity objects using the Engine's GetEntity methods.

GetEntity Method Overloads

// Get entity by GUID - returns base Entity type
Entity entity = engine.GetEntity(entityGuid);

// Get entity by GUID with query parameter - control server querying
Entity entity = engine.GetEntity(entityGuid, query: true);

// Get entity by GUID with generic type - returns specific type
Camera camera = engine.GetEntity<Camera>(cameraGuid);
Cardholder cardholder = engine.GetEntity<Cardholder>(cardholderGuid);

// Get entity by GUID with generic type and query parameter
Camera camera = engine.GetEntity<Camera>(cameraGuid, query: true);

// Get entity by EntityType and LogicalId
Camera entity = (Camera)engine.GetEntity(EntityType.Camera, logicalId);
Camera camera = engine.GetEntity<Camera>(EntityType.Camera, logicalId);

The query parameter determines whether to query the server if the entity is not present in the local cache:

  • true: Query the server if the entity is not in cache (default behavior when parameter is omitted)
  • false: Only return the entity if it's already in the local cache

Usage Examples

// Basic retrieval
Camera camera = engine.GetEntity<Camera>(cameraGuid);
if (camera != null)
{
    Console.WriteLine($"Camera: {camera.Name}");
}

// Using LogicalId (when available)
if (camera.LogicalId.HasValue)
{
    // Retrieve same camera using LogicalId
    Camera sameCamera = engine.GetEntity<Camera>(EntityType.Camera, camera.LogicalId.Value);
}

Creating Entities

The Engine provides several methods for creating different types of entities.

CreateEntity Method

General entity creation method that works with any entity type:

// Create any entity type using EntityType enumeration
var cardholder = (Cardholder)engine.CreateEntity("John Doe", EntityType.Cardholder);
var camera = (Camera)engine.CreateEntity("Lobby Camera", EntityType.Camera);
var area = (Area)engine.CreateEntity("Building A", EntityType.Area);

// Create with parent relationship (applicable to Device, AccessPoint, and IntrusionArea)
var parentArea = engine.GetEntity<Area>(parentAreaGuid);
var childArea = (Area)engine.CreateEntity("Floor 1", EntityType.Area, parentArea.Guid);

// Create with parent and pre-specified GUID
var predefinedGuid = Guid.NewGuid();
var device = (Device)engine.CreateEntity("Custom Device", EntityType.Device, parentGuid, predefinedGuid);

The CreateEntity method has three overloads:

  • CreateEntity(name, entityType): Creates an entity with an auto-generated GUID
  • CreateEntity(name, entityType, parent): Creates an entity with a parent relationship
  • CreateEntity(name, entityType, parent, entityGuid): Creates an entity with a pre-specified GUID

Note

The parent parameter is applicable to Device, AccessPoint, and IntrusionArea entity types. To place other entity types under an Area, create the entity first and then use the Area's Add methods.

CreateAccessRule Method

Specialized method for creating access rules:

// Create different types of access rules
var accessRule = engine.CreateAccessRule("Standard Access", AccessRuleType.Permanent);
var temporaryRule = engine.CreateAccessRule("Temporary Access", AccessRuleType.Temporary);

CreateCustomEntity Method

Method for creating custom entity instances:

// Create custom entity using custom entity type GUID
var customEntityTypeId = new Guid("12345678-1234-1234-1234-123456789ABC");
CustomEntity sensor = engine.CreateCustomEntity("Temperature Sensor 001", customEntityTypeId);

// Create custom entity with parent
var parentEntity = engine.GetEntity(parentEntityGuid);
CustomEntity childSensor = engine.CreateCustomEntity("Child Sensor", customEntityTypeId, parentEntity.Guid);

CreateAccessPoint Method

Method for creating access points:

// Create access point with parent door
var parentDoor = engine.GetEntity<Door>(doorGuid);
var rex = engine.CreateAccessPoint("Request To Exist", AccessPointType.Rex, parentDoor.Guid);

var doorSensor = engine.CreateAccessPoint("Request Door Sensor", AccessPointType.DoorSensor, parentDoor.Guid);

var lockSensor = engine.CreateAccessPoint("Lock Sensor", AccessPointType.LockSensor, parentDoor.Guid);

CreateDevice Method

Method for creating devices:

// Create reader device
var parentUnit = engine.GetEntity<Unit>(unitGuid);
var readerDevice = engine.CreateDevice("Reader", DeviceType.Reader, parentUnit.Guid);

// Create input device  
var inputDevice = engine.CreateDevice("Input", DeviceType.Input, parentUnit.Guid);

// Create output device
var outputDevice = engine.CreateDevice("Output", DeviceType.Output, parentUnit.Guid);

Modifying Entities

Entity properties can be modified directly. Changes are automatically sent to the Directory Server as the entity is modified.

Cardholder

// Get and modify a cardholder
var cardholder = engine.GetEntity<Cardholder>(cardholderGuid);
cardholder.FirstName = "John";
cardholder.LastName = "Smith";
cardholder.EmailAddress = "john.smith@company.com";
cardholder.MobilePhoneNumber = "+1-555-0123";

Camera

// Modify a camera
var camera = engine.GetEntity<Camera>(cameraGuid);
camera.Name = "Updated New Camera Name";
camera.Description = "Updated camera description";

User

// User properties
var user = engine.GetEntity<User>(userGuid);
user.FirstName = "Admin";
user.LastName = "User";
user.EmailAddress = "admin@company.com";

Area

// Area properties
var area = engine.GetEntity<Area>(areaGuid);
area.Name = "Building A";
area.Description = "Main office building";

Deleting Entities

Entities can be deleted using the DeleteEntity method on the Engine.

DeleteEntity Method Overloads

// Delete by GUID
engine.DeleteEntity(entityGuid);

// Delete using entity reference
Entity entity = engine.GetEntity(entityGuid);
engine.DeleteEntity(entity);

Security Center SDK


Macro SDK Developer Guide


Web SDK Developer Guide

  • Getting Started Setup, authentication, and basic configuration for the Web SDK.
  • Referencing Entities Entity discovery, search capabilities, and parameter formats.
  • Entity Operations CRUD operations, multi-value fields, and method execution.
  • Partitions Managing partitions, entity membership, and user access control.
  • Custom Fields Creating, reading, writing, and filtering custom entity fields.
  • Custom Card Formats Managing custom credential card format definitions.
  • Actions Control operations for doors, cameras, macros, and notifications.
  • Events and Alarms Real-time event monitoring, alarm monitoring, and custom events.
  • Incidents Incident management, creation, and attachment handling.
  • Reports Activity reports, entity queries, and historical data retrieval.
  • Performance Guide Optimization tips and best practices for efficient API usage.
  • Reference Entity GUIDs, EntityType enumeration, and EventType enumeration.
  • Under the Hood Technical architecture, query reflection, and SDK internals.
  • Troubleshooting Common error resolution and debugging techniques.

Media Gateway Developer Guide


Web Player Developer Guide

Clone this wiki locally