-
Notifications
You must be signed in to change notification settings - Fork 4
plugin sdk queries
Plugins respond to queries from clients (Security Desk, Config Tool, Web SDK). Understanding the query flow is essential for proper implementation.
Client (Security Desk)
↓
Sends ReportQuery
↓
Directory
↓
Distributes to roles based on SupportedQueries
↓
Plugin Host receives query
↓
Filters based on SupportedQueries
↓
Calls Plugin.OnQueryReceived()
↓
Plugin processes and sends results
↓
Results flow back through Directory to Client
Key points:
- Directory broadcasts queries to all roles
- Plugin Host filters based on
SupportedQueries - Plugin receives only queries it supports
- Plugin must send results and completion
- Queries are processed on a dedicated thread
Plugins must explicitly declare which query types they support by overriding SupportedQueries:
public override List<ReportQueryType> SupportedQueries =>
new List<ReportQueryType>
{
ReportQueryType.DoorActivity,
ReportQueryType.AuditTrails,
ReportQueryType.Custom
};Important
- Only queries in
SupportedQueriesare routed to your plugin
- The Plugin Host automatically filters queries before calling
OnQueryReceived() - If
SupportedQueriesis empty or not overridden, plugin receives no queries - Custom queries require additional filtering by
CustomReportId
This abstract method must be implemented by all plugins:
protected override void OnQueryReceived(ReportQueryReceivedEventArgs args)
{
// Called on query thread
// Process query and send results
}Method is called when:
- A query matching
SupportedQueriesis received - Query has been filtered by the Plugin Host
- Client is waiting for response
Query thread context:
- Called on a dedicated query processing thread
- Must not block for long periods
- Should process quickly or delegate to async task
| Property | Type | Description |
|---|---|---|
Query |
ReportQuery |
The query to process. Cast to specific type (e.g., CustomQuery) as needed. |
MessageId |
int |
Message identifier for this query request. Use with QuerySource to uniquely identify a query. |
QuerySource |
Guid |
Unique identifier of the Application that sent the query. Combined with MessageId to uniquely identify the request. |
DispatchedSystems |
List<Guid> |
Systems the query has been dispatched to. |
Note
MessageId alone is not unique across multiple clients. Always use both MessageId and QuerySource together to identify a specific query request.
When OnQueryReceived() is called, you must:
- Don't block - Return quickly or process asynchronously
-
Send results - Use
Engine.ReportManager.SendQueryResult()for each result batch -
Always complete - Must call
SendQueryCompleted()even if no results - Handle errors gracefully - Catch exceptions and report errors
protected override void OnQueryReceived(ReportQueryReceivedEventArgs args)
{
try
{
// Process query...
ProcessQuery(args.Query);
}
finally
{
// ALWAYS send query completed
Engine.ReportManager.SendQueryCompleted(
args.MessageId,
args.QuerySource,
PluginGuid,
success: true,
ReportError.None,
string.Empty);
}
}If you don't call SendQueryCompleted(), the client waits until timeout.
OnQueryReceived called
↓
Process query (may take time)
↓
For each batch of results:
SendQueryResult(messageId, results)
↓
When all results sent:
SendQueryCompleted(messageId, ...)
Used to send result data to the client:
var results = new ReportQueryResults(ReportQueryType.DoorActivity)
{
Results = dataSet, // DataSet containing result tables
QuerySource = args.QuerySource,
ResultSource = PluginGuid,
Succeeded = true
};
Engine.ReportManager.SendQueryResult(args.MessageId, results);Key points:
- Can be called multiple times for the same query (streaming results)
- Each call sends a batch of data
- Client receives results incrementally
- Use appropriate
ReportQueryResultstype for query
Signals that no more results will be sent:
Engine.ReportManager.SendQueryCompleted(
messageId: args.MessageId,
querySource: args.QuerySource,
resultSource: PluginGuid,
success: true,
error: ReportError.None,
errorMessage: string.Empty
);Parameters:
-
success- true if query succeeded, false if error -
error-ReportErrorenumeration value -
errorMessage- Optional error details for client
For ReportQueryType.Custom, you must filter by CustomReportId:
public override List<Guid> SupportedCustomReports =>
new List<Guid> { CustomReportPageGuid };
protected override void OnQueryReceived(ReportQueryReceivedEventArgs args)
{
if (args.Query is CustomQuery customQuery)
{
if (customQuery.CustomReportId == CustomReportPageGuid)
{
// Handle this custom report
HandleCustomReport(customQuery);
}
}
Engine.ReportManager.SendQueryCompleted(...);
}Custom query workflow:
- Add
ReportQueryType.CustomtoSupportedQueries - Override
SupportedCustomReportswith your report GUIDs - Check
CustomReportIdinOnQueryReceived() - Only process queries matching your GUIDs
Clients can cancel queries that are taking too long, or the Directory may cancel queries that timeout:
protected override void OnQueryCancelled(ReportQueryCancelledEventArgs args)
{
// Cancel any ongoing work for this query
// No need to call SendQueryCompleted() for cancellations
}| Property | Type | Description |
|---|---|---|
MessageId |
int |
Message identifier of the original query request. Use with QueryId to locate the query to cancel. |
QueryId |
Guid |
Unique identifier matching ReportQuery.QueryId of the original query. |
SystemsToCancel |
IEnumerable<Guid> |
External systems for which this query should be cancelled. Check if your PluginGuid is in this list. |
Cancellation notes:
- Cancellations are informational - no response required
- May come from clients or from Directory timeouts
- Use to clean up resources for long-running queries
- Check
SystemsToCancelto see if cancellation applies to your plugin
Don't block the query thread - process asynchronously:
protected override void OnQueryReceived(ReportQueryReceivedEventArgs args)
{
Task.Run(() =>
{
try
{
// Long-running query processing
var results = ProcessQuery(args.Query);
Engine.ReportManager.SendQueryResult(args.MessageId, results);
}
catch (Exception ex)
{
Logger.TraceError(ex, "Query processing failed");
}
finally
{
Engine.ReportManager.SendQueryCompleted(
args.MessageId, args.QuerySource, PluginGuid,
success: true, ReportError.None, string.Empty);
}
});
}Plugins can respond to any ReportQueryType by adding it to SupportedQueries. Common types include:
| Category | Query Types |
|---|---|
| Access Control |
CardholderActivity, DoorActivity, AreaActivity, ElevatorActivity, CredentialActivity, UnitActivity, ZoneActivity, AccessPointActivity
|
| Video |
CameraEvent, VideoMotionEvent, VideoFile, VideoSequence, ArchiverEvent
|
| Intrusion |
IntrusionAreaActivity, IntrusionUnitActivity, IntrusionDetectionActivity
|
| Health |
Health, HealthEvent, HealthStatistics
|
| LPR |
LprReads, LprHits, PatrollerPositions
|
| Custom |
Custom (requires SupportedCustomReports) |
| Other |
AuditTrails, ActivityTrails, EntityState, Thumbnail
|
See the ReportQueryType enum for the complete list.
For large result sets, send data in chunks:
const int ChunkSize = 1000;
var allResults = GetQueryResults(args.Query);
for (int i = 0; i < allResults.Count; i += ChunkSize)
{
var chunk = allResults.Skip(i).Take(ChunkSize).ToList();
var dataSet = CreateDataSet(chunk);
var results = new ReportQueryResults(args.Query.ReportQueryType)
{
Results = dataSet,
QuerySource = args.QuerySource,
ResultSource = PluginGuid,
Succeeded = true
};
Engine.ReportManager.SendQueryResult(args.MessageId, results);
}- Plugin SDK Overview - Plugin architecture
- Plugin SDK Threading - Threading considerations for query handlers
- Plugin SDK Lifecycle - When queries are processed
- SDK Transactions - Entity operations in query processing
- Logging - Query logging
-
Security Center SDK Developer Guide Overview of the SDK framework and how to build integrations with Security Center.
-
Platform SDK
- Platform SDK Overview Introduction to the Platform SDK and core concepts.
- SDK Certificates Details certificates, licensing, and connection validation.
- Entity Guide Explains the core entity model, inheritance, and how to work with entities.
- Entity Cache Guide Describes the engine's local entity cache and synchronization.
- SDK Transactions Covers batching operations for performance and consistency.
- ReportManager Querying entities and activity data from Security Center.
- Events and Actions Subscribing to events and handling actions.
- Logging with the Genetec SDK How to configure logging, diagnostics, and debug methods.
- Referencing SDK Assemblies Best practices for referencing assemblies and resolving them at runtime.
- SDK Compatibility Guide Understanding backward compatibility and versioning in the SDK.
-
Plugin SDK
- Plugin SDK Overview Introduction to plugin architecture and capabilities.
- Plugin SDK Certificates SDK certificate requirements for plugin roles.
- Plugin SDK Lifecycle Initialization and disposal patterns.
- Plugin SDK Threading Threading model, QueueUpdate, and async patterns.
- Plugin SDK Configuration Configuration storage and monitoring.
- Plugin SDK Restricted Configuration Secure credential storage and admin-only configuration.
- Plugin SDK Database Database integration and schema management.
- Plugin SDK Events Event subscription and handling.
- Plugin SDK Queries Query processing and response handling.
- Plugin SDK Request Manager Request/response communication with clients.
- Plugin SDK Entity Ownership Understanding plugin-owned entities, running state management, and ownership release.
- Plugin SDK Entity Mappings Using EntityMappings for plugin-specific configuration and external system integration.
- Plugin SDK State Management Reporting plugin health and diagnostics.
- Plugin SDK Server Management High availability and server failover.
- Custom Privileges Defining and enforcing custom privileges.
- Resolving Non-SDK Assemblies Handling third-party dependencies in plugins and workspace modules.
- Deploying Plugins Registering and deploying plugins and workspace modules.
-
- Macro SDK Developer Guide Complete guide to creating server-side automation scripts in Security Center using C#.
- 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 Guide Setup and configuration of the Media Gateway role for video streaming.
- Web Player Guide Complete guide to integrating GWP for live and playback video streaming.
- Web Player API Reference Full API documentation with interfaces, methods, properties, and events.
- Web Player Sample Application Comprehensive demo showcasing all GWP features with timeline and PTZ controls.
- Genetec Web Player Multiplexing Sample Multi-camera grid demo using a shared WebSocket connection.