-
Notifications
You must be signed in to change notification settings - Fork 6
plugin sdk overview
The Plugin SDK enables you to create advanced, fully embedded integrations that function as custom roles within Security Center.
Before diving into plugin development, it's important to understand the concept of Roles in Security Center, as plugins function as custom roles within the system.
In Security Center, Roles are components that perform specific tasks within the system. Each role is associated with one or more servers, which host and execute the role's functions. Roles are essential for various operations such as managing video units, archiving data, or synchronizing users with corporate directories.
- Role type: Each role has a defined type that determines its specific functions. For example, a role could be responsible for managing video units and their associated archives.
- Role settings: These settings specify the parameters within which the role operates, such as data retention periods or database configurations.
- Server assignment: Roles can be assigned to one or multiple servers. This allows for load balancing and failover capabilities.
- Failover support: Roles support failover, meaning they can automatically switch to a secondary server if the primary server fails, ensuring continuous operation of critical system functions.
When you develop a plugin using the Plugin SDK, you're creating a custom role within Security Center. Your plugin inherits many of the core features of roles, including:
- The ability to define a specific role type with custom functionality
- Configurable settings for your plugin's operation
- Automatic server assignment and failover support
- Built-in health monitoring and database support
This architecture allows your plugin to seamlessly integrate with Security Center's existing infrastructure and benefit from its robust server-side capabilities.
Plugins execute on Security Center servers, not on client machines running Config Tool or Security Desk. This means:
- Plugins have access to server resources and file systems
- File paths in plugins refer to the server's file system
- The Engine is pre-authenticated, no login required
Before building plugins, you should be familiar with:
Plugins are built on top of the Platform SDK. The Plugin SDK provides the hosting infrastructure and lifecycle management, but all entity operations, queries, events, and transactions use the Platform SDK through the Engine property.
Essential Platform SDK guides:
- Entity Guide - Core entity model and operations
- Entity Cache Guide - Understanding the Engine cache
- SDK Transactions - Batching entity operations
All Platform SDK concepts apply to plugins - entities, transactions, queries, events, and caching all work the same way through the Engine property.
Plugins require an SDK certificate to authenticate with Security Center. See:
- Plugin SDK Certificates - Certificate requirements for plugin roles
- SDK Certificates for Integrations - General certificate and licensing information
- Security Center SDK installed
- Visual Studio 2022 or later
- .NET Framework 4.8 or .NET 8 (Security Center 5.13+)
- SDK certificate from Genetec (development or production)
- License with Plugin SDK part number
Unlike client applications that create their own Engine and call LogOnAsync(), plugins are hosted by Security Center's plugin infrastructure:
flowchart TB
subgraph Host[Plugin role host]
direction TB
S1[Load plugin assembly] --> S2[Create plugin instance]
S2 --> S3[Validate SDK certificate]
S3 --> S4[Create Engine]
S4 --> S5[Initialize plugin]
S5 --> S6[Start database layer if supported]
S6 --> S7[Start plugin]
end
The plugin host handles:
- Plugin assembly loading and instantiation
- Certificate validation against license
- Engine creation and initialization
- Lifecycle management (start, stop, restart)
- Database initialization (if supported)
- State reporting to Config Tool
A plugin consists of three essential parts:
1. Plugin Class - Your implementation inheriting from Genetec.Sdk.Plugin.Plugin
- Receives a fully-initialized
Engineinstance - Implements abstract
OnQueryReceived()method - Implements abstract
Dispose(bool disposing)method - Overrides lifecycle methods (
OnPluginLoaded(),OnPluginStart())
2. PluginDescriptor Class - Metadata and registration information
- Defines plugin name, description, and unique GUID
- Specifies default configuration
- Optional: Defines images for UI representation
- Optional: Specifies if plugin is single-instance
- Optional: Specifies 64-bit execution requirement
- Optional: Defines plugin category (ServiceDomain)
- Optional: Lists certificate application IDs
PluginDescriptor properties:
| Property | Type | Required | Description |
|---|---|---|---|
Name |
string |
Yes | Plugin display name shown in Config Tool |
Description |
string |
Yes | Plugin description |
PluginGuid |
Guid |
Yes | Unique identifier for the plugin type |
SpecificDefaultConfig |
string |
Yes | Default XML configuration for new instances |
ServiceDomain |
string |
No | Plugin category for grouping. Defaults to Name
|
Supports64Bits |
bool |
No | Whether plugin requires 64-bit process. Defaults to true
|
IsSingleInstance |
bool |
No | Whether only one instance can exist. Defaults to false
|
SmallImage |
Bitmap |
No | 64x64 PNG icon for entity browsers |
LargeImage |
Bitmap |
No | 256x256 PNG icon for configuration pages |
ApplicationId |
List<string> |
No | Certificate application IDs for authentication |
public class MyPluginDescriptor : PluginDescriptor
{
public override string Name => "My Integration Plugin";
public override string Description => "Integrates with external system";
public override Guid PluginGuid => new Guid("{12345678-1234-1234-1234-123456789012}");
public override string SpecificDefaultConfig => "<Config />";
// Optional: Plugins with the same ServiceDomain share a host process
public override string ServiceDomain => "External Integrations";
// Optional: Set to false if plugin must run in 32-bit process
public override bool Supports64Bits => true;
// Optional: Prevent multiple instances
public override bool IsSingleInstance => true;
// Optional: Must match the ApplicationId in your .cert file
public override List<string> ApplicationId => new List<string>
{
"KxsD11z743Hf5Gq9mv3+5ekxzemlCiUXkTFY5ba1NOGcLCmGstt2n0zYE9NsNimv"
};
}Controls whether the plugin runs in a 64-bit or 32-bit process.
| Value | Effect |
|---|---|
true (default) |
Plugin runs in a 64-bit process |
false |
Plugin runs in a 32-bit process |
Set to false when:
- Plugin uses 32-bit native DLLs that have no 64-bit version
- Plugin depends on 32-bit COM components
- Plugin integrates with legacy hardware SDKs that are 32-bit only
Keep as true (default) when:
- Plugin has no native dependencies
- Plugin uses 64-bit native libraries
- Plugin can run in 64-bit mode (recommended for performance and memory)
Groups plugin roles into process hosting containers. Roles with the same ServiceDomain value share a single RoleController process and a single Directory proxy connection.
Default: Returns Name property value
How it affects hosting:
| Same ServiceDomain | Different ServiceDomain |
|---|---|
| Roles share same process | Roles run in separate processes |
| Roles share same Directory proxy | Each role has its own proxy |
| Lower resource usage | Higher isolation |
Impact of failures:
| Failure Type | Impact on Other Plugins in Same ServiceDomain |
|---|---|
| Process crash | All plugins stop and restart together |
| Deactivate plugin (Config Tool) | Only that plugin stops, others continue |
| Plugin throws exception | Usually isolated, others continue |
| Delete plugin role | Only that plugin stops, others continue |
The host process manages each plugin role independently. Administrative actions like deactivation or deletion only affect the targeted plugin. However, if the host process itself crashes, all plugins sharing that ServiceDomain are affected since they run in the same process.
When to customize:
- Use the same value across related plugin types if they should share resources
- Use unique values if plugins should be completely isolated
- Keep the default for most cases
Tip
Spaces are automatically stripped from ServiceDomain values.
Memory optimization: Plugins sharing the same ServiceDomain also share the same entity cache. In systems with hundreds of thousands of entities (cardholders, cameras, doors), this can save gigabytes of memory. Instead of each plugin instance loading and caching the same entities separately, they share a single cache. Consider using a shared ServiceDomain when multiple plugin instances need access to the same large entity sets.
Provides certificate-based authentication by specifying which certificate ApplicationIds are valid for this plugin. Acts as a whitelist for certificate validation during plugin initialization.
Default: Empty list (validation skipped for backward compatibility)
How it works:
- When the plugin starts, Security Center reads the ApplicationId from the plugin's
.certfile - The certificate's ApplicationId is compared against each entry in this list
- If a match is found, the plugin continues to license validation
- If no match is found, the plugin fails with
IllegitimateCertificateerror
When ApplicationId is empty (default):
- Certificate legitimacy check is skipped
- Only license registration is validated
- Provides backward compatibility for older plugins
When ApplicationId contains values:
- The
.certfile's ApplicationId must match one of the entries in this list - If no match is found, plugin initialization fails with
IllegitimateCertificateerror - This ensures the deployed certificate file is one specifically issued for this plugin
Why it is a list: The list structure allows a plugin to accept multiple valid certificates. This supports scenarios where:
- Different deployment environments use different certificates
- Multiple partners deploy the same plugin with their own certificates
3. Certificate File - Authentication and licensing
- Must be named
{Namespace}.{ClassName}.cert(e.g.,Genetec.Dap.MyPlugin.cert) - Placed in a
Certificatesfolder next to the plugin DLL - Contains ApplicationId that validates against license
- See Plugin SDK Certificates for details
This is a critical concept: There are TWO different GUIDs to understand:
public class MyPluginDescriptor : PluginDescriptor
{
public override Guid PluginGuid => new Guid("{12345678-1234-1234-1234-123456789012}");
public override string Name => "My Plugin";
}This GUID identifies:
- The type of plugin (like a class definition)
- The plugin DLL and its capabilities
- What appears in Config Tool when adding a new role
- Hardcoded in your PluginDescriptor - same for all instances
Analogy: Like a product SKU - identifies WHAT the plugin is.
public class MyPlugin : Plugin
{
protected override void OnPluginLoaded()
{
// This is the ROLE INSTANCE GUID - different for each instance!
Logger.TraceInformation($"My role instance GUID: {PluginGuid}");
// Access the Role entity
var role = Engine.GetEntity<Role>(PluginGuid);
Logger.TraceInformation($"Role name: {role.Name}");
}
}This GUID identifies:
- A specific instance of the plugin type (object instance)
- The Role entity in the Security Center database
- Unique for each role - even if same plugin type
- Generated by Security Center when administrator adds the role
Analogy: Like a serial number - identifies THIS specific instance.
flowchart TB
A["PluginDescriptor.PluginGuid = AAAA-AAAA
(Plugin Type)"]
A --> B[Administrator adds plugin role in Config Tool]
B --> C[Security Center creates Role entity]
C --> D["Role.Guid = BBBB-BBBB
(Instance 1)"]
D --> E[Plugin host creates Plugin instance]
E --> F["Plugin.PluginGuid = BBBB-BBBB
(Role instance GUID)"]
A --> H[Administrator adds ANOTHER instance of SAME plugin]
H --> I[Security Center creates ANOTHER Role entity]
I --> J["Role.Guid = CCCC-CCCC
(Instance 2)"]
J --> K[Plugin host creates ANOTHER Plugin instance]
K --> L["Plugin.PluginGuid = CCCC-CCCC
(Different role instance GUID)"]
Use Plugin.PluginGuid (role instance GUID) for:
- Accessing your role's configuration
- Checking entity ownership
- Identifying your specific instance
- Inter-role communication
protected override void OnPluginLoaded()
{
// Access THIS role instance's configuration
var role = Engine.GetEntity<Role>(PluginGuid);
var config = role.SpecificConfiguration;
// Check if an entity belongs to THIS instance
var entity = Engine.GetEntity(entityGuid);
if (entity.OwnerRole == PluginGuid)
{
// This entity belongs to THIS plugin instance
}
}Use PluginDescriptor.PluginGuid (plugin type ID) for:
- Finding ALL instances of your plugin type
- Type-level operations
- Rarely used in plugin code
// Find all instances of this plugin type
// Note: This requires the GUID from your PluginDescriptor class
var myPluginTypeGuid = new Guid("{12345678-1234-1234-1234-123456789012}");
// This is NOT directly accessible from Plugin.PluginGuid - that's the role instance GUID- Plugin.PluginGuid is a ROLE instance GUID - it's different for each instance
- PluginDescriptor.PluginGuid is a PLUGIN TYPE GUID - same for all instances
- Role entity GUID == Plugin.PluginGuid - they're the same thing
- Multiple instances of the same plugin have different Plugin.PluginGuid but same PluginDescriptor.PluginGuid
- Use Plugin.PluginGuid for 99% of operations - it identifies YOUR specific instance
When a plugin role starts:
- Descriptor resolution - Loads the plugin descriptor for the role subtype
- Assembly loading - Loads the plugin assembly and dependencies
- Plugin instantiation - Creates the plugin class instance
- Certificate validation - Validates the SDK certificate against the license
- Engine creation - Creates the Engine instance
-
Initialization - Calls
Initialize(engine, roleGuid, culture)and runsOnPluginLoaded() -
Database setup - If
IPluginDatabaseSupport, starts the database layer -
Plugin start - Calls
OnPluginStart()
Key Points:
- Engine is pre-authenticated - no
LogOnAsync()needed - Multiple instances of the same plugin can run if
IsSingleInstance = false - Each plugin role instance gets its own Engine and Plugin instance
Your plugin receives a fully-initialized IEngine instance through the Initialize() method:
protected internal IEngine Engine { get; private set; }This Engine provides access to all Platform SDK functionality:
- Entity operations (
CreateEntity,GetEntity,DeleteEntity) - Transaction management (
TransactionManager) - Query processing (
ReportManager) - Event subscriptions (
SetEventFilter,EventReceived) - Action handling (
ActionReceived) - Request/response communication (
RequestManager) - Entity change notifications (
EntitiesInvalidated)
Critical difference from client applications:
- No login required - Engine is already authenticated
- Server context - Runs under admin account
For all entity operations, queries, events, and transactions, refer to the Platform SDK guides. The Plugin SDK adds hosting and lifecycle management on top of the Platform SDK foundation.
Plugins can implement various capabilities by overriding methods and implementing interfaces:
- Lifecycle Management - Initialize, start, and clean up resources
- Query Processing - Respond to report queries from clients
- Event Handling - Subscribe to and process system events
- Action Handling - Respond to actions from clients
- Entity Management - Create and manage entities (see Plugin SDK Entity Ownership)
- Database Integration - Persistent storage with SQL Server
- Configuration Management - Store and manage plugin settings
- Restricted Configuration - Secure credential storage and admin-only configuration
- State Reporting - Report health and diagnostics
- Request Handling - Handle custom client requests
- Server Management - Control high availability and failover
Each capability is covered in detail in its dedicated guide.
- Create the plugin class. Inherit from
Pluginand implement abstract methods. - Create the
PluginDescriptor. Define metadata and default configuration. - Implement the lifecycle. Override
OnPluginLoaded()for initialization. - Register the plugin. Add registry entries or XML configuration.
- Deploy the certificate. Place the
.certfile in the Certificates folder. - Test in development. Add the plugin role in Config Tool.
- Handle queries and events. Implement business logic.
- Deploy to production. Register on production servers with the production certificate.
For deployment details, see Deploying plugins.
- Deploying plugins: Plugin packaging, registration, and deployment.
- Plugin SDK configuration: Role-level configuration storage and update flow.
- Plugin SDK custom privileges: Defining custom privileges for plugin features.
-
Plugin SDK database: SQL Server integration through
IPluginDatabaseSupport. - Plugin SDK entity mappings: External system integration.
- Plugin SDK entity ownership: Plugin-owned entities and their running-state contract.
- Plugin SDK events: Subscribing to events from a plugin role.
- Plugin SDK lifecycle: Plugin initialization, startup, and disposal phases.
- Plugin SDK queries: Implementing custom report queries in a plugin.
- Plugin SDK request manager: Request and response communication between plugin and config pages.
- Plugin SDK restricted configuration: Encrypted configuration values for credentials and admin settings.
- Plugin SDK server management: High availability and failover for plugin roles.
- Plugin SDK state management: Reporting plugin and entity health to Config Tool.
- Plugin SDK threading: Engine thread, QueueUpdate, and async patterns for plugins.
- About plugin assembly resolution: Resolving non-SDK assemblies that the plugin depends on.
-
About entities: Entity model and
IPartitionSupport. - About the Engine entity cache: How the Engine caches entity data locally.
- About transactions: Batching multiple entity operations into one request.
- About logging: SDK logging configuration and severity levels.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- SDK compatibility
- Entities
- Entity cache
- Transactions
- Events
- Actions
- Security Desk
- Custom events
- ReportManager
- ReportManager query reference
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Mobile credentials
- Logging
- Overview
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- .NET 8 support
- Overview
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual 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
- 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
- Under the hood
- Troubleshooting