-
Notifications
You must be signed in to change notification settings - Fork 4
Plugin SDK Events
Plugins can subscribe to and receive events from Security Center entities. This guide covers plugin-specific event handling patterns.
For general event and action concepts, see Platform SDK Events and Actions.
Plugins have two ways to declare which events they want to receive:
Override SupportedEventSubscription to declaratively specify event types at the class level:
public class MyPlugin : Plugin
{
public override List<EventType> SupportedEventSubscription => new List<EventType>
{
EventType.AccessGranted,
EventType.AccessDenied,
EventType.DoorOpenTooLong,
EventType.DoorForcedOpen
};
protected override void OnPluginLoaded()
{
Engine.EventReceived += OnEventReceived;
}
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
// Handle events
Logger.TraceDebug($"Event received: {e.EventType} from {e.SourceGuid}");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Engine.EventReceived -= OnEventReceived;
}
}
}When to use:
- Event types are known at compile time
- Event subscription does not change during plugin lifetime
- Cleaner separation between declaration and handling
Use Engine.SetEventFilter() for dynamic event subscription in OnPluginLoaded():
protected override void OnPluginLoaded()
{
// Set event filter dynamically
Engine.SetEventFilter(new List<EventType>
{
EventType.AccessGranted,
EventType.AccessDenied,
EventType.DoorOpenTooLong
});
Engine.EventReceived += OnEventReceived;
}When to use:
- Event types depend on configuration
- Event subscription changes at runtime
- Need to add/remove event types dynamically
The Engine provides several methods for managing event filters:
| Method | Description |
|---|---|
SetEventFilter(IEnumerable<EventType>) |
Sets the event filter, replacing previous filters |
AddToEventFilter(EventType) |
Adds a single event type to the current filter |
RemoveFromEventFilter(EventType) |
Removes a single event type from the current filter |
GetEventFilter() |
Returns the current list of filtered event types |
ClearEventFilter() |
Clears the filter to receive all events |
// Add event type based on configuration
if (config.MonitorDoorEvents)
{
Engine.AddToEventFilter(EventType.DoorOpenTooLong);
Engine.AddToEventFilter(EventType.DoorForcedOpen);
}
// Remove event type when no longer needed
Engine.RemoveFromEventFilter(EventType.DoorOpenTooLong);
// Get current filter
List<EventType> currentFilter = Engine.GetEventFilter();Subscribe to Engine.EventReceived to receive events:
protected override void OnPluginLoaded()
{
Engine.SetEventFilter(new List<EventType>
{
EventType.AccessGranted,
EventType.AccessDenied
});
Engine.EventReceived += OnEventReceived;
}
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
switch (e.EventType)
{
case EventType.AccessGranted:
HandleAccessGranted(e);
break;
case EventType.AccessDenied:
HandleAccessDenied(e);
break;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Engine.EventReceived -= OnEventReceived;
}
}| Property | Type | Description |
|---|---|---|
EventType |
EventType |
The type of event received |
SourceGuid |
Guid |
The entity GUID that generated the event |
Timestamp |
DateTime |
When the event occurred (UTC) |
GroupId |
Guid |
Context identifier for grouping related events |
Event |
Event |
The underlying Event object with additional data |
Cast EventReceivedEventArgs to specialized types for specific event data:
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
if (e is AccessControlEventReceivedEventArgs accessEvent)
{
Logger.TraceDebug($"Access event at {accessEvent.AccessPointGuid}");
}
else if (e is CustomEventReceivedEventArgs customEvent)
{
Logger.TraceDebug($"Custom event: {customEvent.CustomEventId}, Message: {customEvent.Message}");
}
else if (e is AlarmTriggeredRoutableEventArgs alarmEvent)
{
Logger.TraceDebug($"Alarm triggered: {alarmEvent.AlarmTriggeredEvent.Alarm}");
}
}Plugins can also receive actions sent to them or their owned entities.
protected override void OnPluginLoaded()
{
Engine.ActionReceived += OnActionReceived;
}
private void OnActionReceived(object sender, ActionReceivedEventArgs e)
{
Logger.TraceDebug($"Action received: {e.ActionType}");
switch (e.ActionType)
{
case ActionType.TriggerAlarm:
HandleTriggerAlarm(e);
break;
case ActionType.Custom:
if (e is CustomActionReceivedEventArgs customAction)
{
HandleCustomAction(customAction);
}
break;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Engine.ActionReceived -= OnActionReceived;
}
}Event handlers are called on the engine thread, making it safe to perform Engine operations directly:
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
// Safe to access Engine directly - we're on the engine thread
var entity = Engine.GetEntity(e.SourceGuid);
Logger.TraceDebug($"Event {e.EventType} from {entity.Name}");
}For operations that take time (network calls, file I/O), offload to a background thread:
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
// Capture event data
var eventData = new EventData
{
EventType = e.EventType,
SourceGuid = e.SourceGuid,
Timestamp = e.Timestamp
};
// Process on background thread
Task.Run(async () =>
{
// Long-running operation (network, database, etc.)
await SendToExternalSystemAsync(eventData);
// Queue entity updates back to engine thread
Engine.QueueUpdate(() =>
{
ModifyPluginState(new PluginStateEntry("LastEvent",
$"Processed {eventData.EventType} at {DateTime.UtcNow}"));
});
});
}public class AccessMonitorPlugin : Plugin
{
private readonly ConcurrentQueue<AccessEvent> m_eventQueue = new();
private CancellationTokenSource m_cancellation;
private Task m_processingTask;
// Declaratively specify supported events
public override List<EventType> SupportedEventSubscription => new List<EventType>
{
EventType.AccessGranted,
EventType.AccessDenied,
EventType.DoorOpenTooLong,
EventType.DoorForcedOpen
};
protected override void OnPluginLoaded()
{
Engine.EventReceived += OnEventReceived;
Engine.ActionReceived += OnActionReceived;
ModifyPluginState(new PluginStateEntry("Status", "Monitoring access events"));
}
protected override void OnPluginStart()
{
// Start background processor
m_cancellation = new CancellationTokenSource();
m_processingTask = Task.Run(() => ProcessEventsAsync(m_cancellation.Token));
}
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
// Quick processing on engine thread
var accessEvent = new AccessEvent
{
EventType = e.EventType,
SourceGuid = e.SourceGuid,
Timestamp = e.Timestamp
};
// Queue for background processing
m_eventQueue.Enqueue(accessEvent);
}
private void OnActionReceived(object sender, ActionReceivedEventArgs e)
{
Logger.TraceDebug($"Action received: {e.ActionType}");
}
private async Task ProcessEventsAsync(CancellationToken cancel)
{
while (!cancel.IsCancellationRequested)
{
if (m_eventQueue.TryDequeue(out var accessEvent))
{
try
{
await SendToExternalSystemAsync(accessEvent);
}
catch (Exception ex)
{
Logger.TraceError(ex, "Failed to process event");
}
}
else
{
await Task.Delay(100, cancel);
}
}
}
private async Task SendToExternalSystemAsync(AccessEvent accessEvent)
{
// Send to external system
await Task.Delay(10); // Simulated network call
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Engine.EventReceived -= OnEventReceived;
Engine.ActionReceived -= OnActionReceived;
m_cancellation?.Cancel();
}
}
}
public class AccessEvent
{
public EventType EventType { get; set; }
public Guid SourceGuid { get; set; }
public DateTime Timestamp { get; set; }
}- Platform SDK Events and Actions - Core event and action concepts
- Plugin SDK Threading - Threading patterns for event handlers
- Plugin SDK Lifecycle - Event handler registration timing
- Plugin SDK Overview - Plugin architecture
-
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.