Skip to content

plugin sdk queries

Andre Lafleur edited this page Feb 3, 2026 · 5 revisions

About plugin queries

Plugins respond to queries from clients (Security Desk, Config Tool, Web SDK). Understanding the query flow is essential for proper implementation.

Query Flow Architecture

sequenceDiagram
    participant Client as Client (Security Desk)
    participant Directory
    participant Host as Plugin Host
    participant Plugin

    Client->>Directory: Send ReportQuery
    Directory->>Host: Distribute to roles with supported report types
    Host->>Host: Filter based on SupportedQueries and SupportedCustomReports
    Host->>Plugin: OnQueryReceived()
    Plugin->>Plugin: Process query
    Plugin-->>Directory: Send results
    Directory-->>Client: Return results
Loading

Key points:

  • Directory distributes queries to roles that registered supported report types
  • SDK filters queries using SupportedQueries and SupportedCustomReports
  • Plugin receives only queries it supports
  • Plugin must send results and completion

Declaring Query Support

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 SupportedQueries are routed to your plugin
  • The SDK filters queries before calling OnQueryReceived()
  • If SupportedQueries is empty or not overridden, the plugin receives no queries
  • Custom queries require filtering by CustomReportId

Processing Queries

OnQueryReceived()

This abstract method must be implemented by all plugins:

protected override void OnQueryReceived(ReportQueryReceivedEventArgs args)
{
    // Process query and send results
}

Method is called when:

  • A query matching SupportedQueries is received
  • For Custom queries, CustomReportId matches SupportedCustomReports
  • Client is waiting for response

Query execution considerations:

  • Return quickly or offload long-running work
  • Use async work for long-running queries

ReportQueryReceivedEventArgs Properties

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.

Query Processing Requirements

When OnQueryReceived() is called, you must:

  1. Don't block - Return quickly or process asynchronously
  2. Send results - Use Engine.ReportManager.SendQueryResult() for each result batch
  3. Always complete - Must call SendQueryCompleted() even if no results
  4. Handle errors gracefully - Catch exceptions and report errors

Query Completion is Mandatory

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, 
            true, 
            ReportError.None, 
            string.Empty);
    }
}

If you don't call SendQueryCompleted(), the client waits until timeout.

Sending Query Results

Result Flow

flowchart TB
    A[OnQueryReceived called] --> B[Process query]
    B --> C{More results?}
    C -->|Yes| D[SendQueryResult<br/>messageId, results]
    D --> C
    C -->|No| E[SendQueryCompleted<br/>messageId, ...]
Loading

SendQueryResult()

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
};

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 ReportQueryResults type for query

SendQueryCompleted()

Signals that no more results will be sent:

Engine.ReportManager.SendQueryCompleted(
    args.MessageId,
    args.QuerySource,
    PluginGuid,
    true,
    ReportError.None,
    string.Empty
);

Parameters:

  • successful - true if query succeeded, false if error
  • error - ReportError enumeration value
  • errorDetail - Optional error details for client

Custom Queries

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:

  1. Add ReportQueryType.Custom to SupportedQueries
  2. Override SupportedCustomReports with your report GUIDs
  3. Check CustomReportId in OnQueryReceived()
  4. Only process queries matching your GUIDs

Query Cancellation

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
}

ReportQueryCancelledEventArgs Properties

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 SystemsToCancel to see if cancellation applies to your plugin

Async Query Processing

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, 
                true, ReportError.None, string.Empty);
        }
    });
}

Supported Query Types

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.

Query Performance Considerations

Chunking Results

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
    };
    
    Engine.ReportManager.SendQueryResult(args.MessageId, results);
}

See also

Security Center SDK

  • Security Center SDK Developer Guide Overview of the SDK framework and how to build integrations with Security Center.

    • Platform SDK

      • Overview Introduction to the Platform SDK and core concepts.
      • Connecting to Security Center Step-by-step guide for connecting and authenticating with the SDK.
      • SDK Certificates Details certificates, licensing, and connection validation.
      • Referencing SDK Assemblies Best practices for referencing assemblies and resolving them at runtime.
      • SDK Compatibility Guide Understanding backward compatibility and versioning in the SDK.
      • 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.
      • Transactions Covers batching operations for performance and consistency.
      • Events Subscribing to real-time system events.
      • Actions Sending actions to Security Center.
      • Security Desk Displaying content on monitors, reading tiles, sending tasks, and messaging operators.
      • Custom Events Defining, raising, and subscribing to custom events.
      • ReportManager Querying entities and activity data from Security Center.
      • ReportManager Query Reference Complete reference of query types, parameters, and response formats.
      • Privileges Checking, querying, and setting user privileges.
      • Partitions Entity organization and access control through partitions.
      • Logging How to configure logging, diagnostics, and debug methods.
    • Plugin SDK

    • Workspace SDK

    • Macro SDK

      • Overview How macros work, creating and configuring macro entities, automation, and monitoring.
      • Developer Guide Developing macro code with the UserMacro class and Security Center SDK.

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.
  • About access control in the Web SDK Concepts, relationships, and common access-control operations.
  • About video in the Web SDK Concepts, relationships, configuration, and common video operations.
  • 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.
  • Tasks Listing and executing saved report tasks.
  • Macros Monitoring currently running macros.
  • Custom Entity Types Listing, retrieving, and deleting custom entity type descriptors.
  • System Endpoints License usage, web tokens, and exception handling.
  • 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

  • Developer Guide Complete guide to integrating GWP for live and playback video streaming.
  • API Reference Full API documentation with interfaces, methods, properties, and events.
  • Sample Application Comprehensive demo showcasing all GWP features with timeline and PTZ controls.
  • Multiplexing Sample Multi-camera grid demo using a shared WebSocket connection.

Clone this wiki locally