Repository navigation
platform sdk events
The Security Center SDK allows applications to subscribe to events from entities in the system and raise events programmatically. Events notify your application when something happens, such as a door opening, a camera going offline, or a custom event being raised.
Note
Events are notifications that something happened. For commands directed at entities your application owns (a request to unlock a door, arm a zone), see Receiving actions. To send commands to entities from your application, use the methods on Engine.ActionManager.
This page covers operational events delivered through Engine.EventReceived, such as access granted, door state, video, and alarm events. To detect changes to entity properties, custom fields, relationships, or entity lifecycle, see Detecting entity changes.
Subscribe to events using Engine.EventReceived:
engine.EventReceived += OnEventReceived;
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
Console.WriteLine($"Event received: {e.EventType} from {e.SourceGuid}");
}By default, the Engine receives every event type for entities in its cache. For an Engine that your application instantiated, use SetEventFilter to replace the current filter with the event types your application must receive:
engine.SetEventFilter(new[] { EventType.DoorOpen, EventType.DoorClose, EventType.AccessGranted });Use AddToEventFilter to add event types to an existing restricted filter. It does not restrict the default all-events filter. Call ClearEventFilter to restore all event types:
engine.ClearEventFilter();In a Workspace SDK extension, SetEventFilter adds the requested event types without replacing filters used by other extensions. In a plugin, SetEventFilter replaces the current filter.
The EventReceivedEventArgs base class can be cast to specialized types that provide event-specific properties. Common examples:
| Type | Description |
|---|---|
LicensePlateReadEventArgs |
License plate recognition (LPR) reads with a Plate property |
LicensePlateHitEventArgs |
LPR hotlist hits |
VideoAnalyticsEventArgs |
Video analytics events |
AccessRequestedEventArgs |
Access requests requiring confirmation |
AlarmTriggeredRoutableEventArgs |
Alarm events with alarm details |
Specialized event argument types also cover parking, pan-tilt-zoom, health monitoring, and other subsystems. Use pattern matching to check the actual type:
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
if (e is LicensePlateReadEventArgs lprEvent)
{
Console.WriteLine($"Plate read: {lprEvent.Plate.Value}");
}
else if (e is VideoAnalyticsEventArgs analyticsEvent)
{
Console.WriteLine($"Analytics event from: {analyticsEvent.SourceGuid}");
}
}LicensePlateReadEventArgs also exposes the read's annotation values as string properties: ConfidenceScore, StateName, VehicleType, VehicleMake, VehicleSpeed, RelativeMotion, CharactersHeight, and Context. Each property reads a specific annotation field: StateName from "State Name", VehicleType from "Vehicle Type", VehicleMake from "Vehicle Make", RelativeMotion from "Relative Motion", CharactersHeight from "Characters Height", ConfidenceScore from "Confidence Score", Context from "Context", and VehicleSpeed from "Speed". The values are present when the ALPR unit supplies the annotation; the matching is not case sensitive. Annotation fields are configured in the ALPR settings of Security Center.
For a custom annotation field, cast e.Event to LprReadEvent and call GetAttributeValue(name), passing the annotation field name; the lookup is not case sensitive and returns null when the field is absent. AttributesXml holds the same data as an XML document, with an Attributes root element whose Attribute child elements carry the field name in a name attribute and the value as element text, if you need to enumerate every field.
All event args expose common properties:
| Property | Type | Description |
|---|---|---|
EventType |
EventType |
The type identifier for the event |
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. For event types without a specialized event class, this is a generic Event instance rather than null. |
When EventReceivedEventArgs.Event is not null, it provides additional properties:
| Property | Type | Description |
|---|---|---|
Type |
EventType |
The event type |
SourceEntity |
Guid |
The source entity GUID |
GroupId |
Guid |
Shared by events that represent the same occurrence so Security Desk shows them as a single entry |
Timestamp |
DateTime |
Event timestamp |
Coordinates |
GeoCoordinate |
Geographic coordinates (if applicable) |
RelatedEntities |
IEnumerable<Guid> |
Related entity GUIDs |
OfflinePeriod |
OfflinePeriodType |
Indicates if the event occurred during an offline period |
The Event property returns the base Event class. Cast it to a specialized class to access event-specific properties:
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
if (e.Event is AccessEvent accessEvent)
{
Console.WriteLine($"Cardholder: {accessEvent.Cardholder}");
Console.WriteLine($"Access point: {accessEvent.AccessPoint}");
}
else if (e.Event is AlarmEvent alarmEvent)
{
Console.WriteLine($"Alarm state: {alarmEvent.AlarmState}");
Console.WriteLine($"Priority: {alarmEvent.Priority}");
}
}| Event class | Description |
|---|---|
AccessEvent |
Access control events with Cardholder, Credentials, AccessPoint
|
AlarmEvent |
Alarm events with AlarmState, Priority, TriggerEntity
|
CameraEvent |
Camera events with VideoEncoderDevice
|
CustomEventInstance |
Custom events with Id, Message
|
The SourceGuid (on EventReceivedEventArgs) or SourceEntity (on the Event object) identifies the entity that generated the event. This is the primary entity the event is about.
Source entity examples include:
- An
AccessGrantedevent can use an area, door, or elevator as its source entity. - A
CameraMotionOnevent uses a camera as its source entity. - A
UnitDisconnectedevent can use an access control, intrusion, license plate recognition, or video unit as its source entity.
An event can have multiple related entities stored in the RelatedEntities collection. The SourceEntity property returns the first entity in this collection. When processing events, use SourceGuid or SourceEntity to identify which entity triggered the event.
The GroupId property enables event de-duplication in the Monitoring task. When multiple events share the same non-empty GroupId, Security Desk displays them as a single entry while still triggering event-to-actions for each individual event.
Use GroupId when multiple components report the same occurrence. For example, if an access control unit and the Access Manager role both report the same access event, assign the same GroupId to both events. Security Desk then displays one entry in the Monitoring task instead of duplicates.
When raising events from multiple sources that represent the same logical occurrence, assign the same GroupId to consolidate their display:
var correlationId = Guid.NewGuid();
var event1 = engine.ActionManager.BuildEvent(EventType.DoorRexOn, door1Guid);
event1.GroupId = correlationId;
var event2 = engine.ActionManager.BuildEvent(EventType.DoorRexOn, door2Guid);
event2.GroupId = correlationId;
engine.ActionManager.RaiseEvent(event1);
engine.ActionManager.RaiseEvent(event2);Both events trigger their configured actions, but the Monitoring task displays only one entry.
The OfflinePeriod property indicates when an event occurred relative to unit connectivity. This applies to events from devices that can store events locally while disconnected from Security Center, such as access control units.
When a unit reconnects after being offline, it uploads stored events to Security Center. The system assigns an OfflinePeriodType based on how old each event is:
| Value | Default threshold | Event-to-actions behavior |
|---|---|---|
None |
Not applicable (online) | All actions execute normally |
GracePeriod |
15 minutes | All actions execute normally |
OfflineAlarmPeriod |
3 days | Only alarm-related actions execute |
Offline |
Beyond 3 days | Event is logged only, no actions execute |
private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
if (e.Event.OfflinePeriod == OfflinePeriodType.Offline)
{
// This event occurred while the unit was offline for an extended period
// No event-to-actions were triggered for this event
}
}You only receive events for entities loaded in the engine's entity cache.
Load a specific entity by GUID:
engine.GetEntity(doorGuid);Load all entities of a type by running a query. The query searches the Directory database and loads matching entities into the cache:
var query = (EntityConfigurationQuery)engine.ReportManager.CreateReportQuery(ReportType.EntityConfiguration);
query.EntityTypeFilter.Add(EntityType.Door);
query.Query();See About the ReportManager for more query options.
See About the Engine entity cache for pagination and efficient entity loading.
Use ActionManager.BuildEvent to create an event and ActionManager.RaiseEvent to send it to Security Center:
Event eventInstance = engine.ActionManager.BuildEvent(EventType.DoorRexOn, doorGuid);
engine.ActionManager.RaiseEvent(eventInstance);The BuildEvent method creates an event instance for the specified event type and source entity. Some event types return specialized classes with additional properties that you can set before raising the event. If the SDK cannot create an event instance for the specified EventType, BuildEvent throws an SdkException.
Each entity has a SupportedEvents property that lists the event types it produces:
var door = engine.GetEntity(doorGuid);
foreach (var eventType in door.SupportedEvents)
{
Console.WriteLine($"Supported: {eventType}");
}SupportedEvents lists the event types that an entity can produce, not the event types that your application can raise. The application type determines which event types your application can raise, as described below.
You can set Timestamp to a past time and OfflinePeriod to indicate the event occurred while offline:
var eventInstance = engine.ActionManager.BuildEvent(EventType.DoorRexOn, doorGuid);
eventInstance.Timestamp = DateTime.UtcNow.AddHours(-2);
eventInstance.OfflinePeriod = OfflinePeriodType.GracePeriod;
engine.ActionManager.RaiseEvent(eventInstance);Not all event types can be raised programmatically. Security Center restricts which events each application type can raise:
| Application type | Can raise |
|---|---|
| SDK application | Custom events on any entity, plus specific event types like camera bookmarks and video analytics |
| Plugin | Events on entities the plugin owns, such as door events on doors managed by an access control plugin |
Calling RaiseEvent with an event type that the current application is not allowed to raise throws an SdkException. Many event types are system-generated only and cannot be raised by any application, such as AlarmTriggered and UserLoggedOn.
Events raised through RaiseEvent are sent to other connected applications that have the source entity loaded, but not to the application that raised them. RaiseEvent does not guarantee persistence. When the SDK provides an entity-specific method for the operation, use that method instead of constructing the corresponding event manually.
See Raising custom events for the event type that all SDK applications can raise on any entity.
When raising multiple events, use an event transaction to batch them together. This sends all events to Security Center in a single request, improving performance.
Create an event transaction, add the prebuilt events, and then commit the transaction:
bool RaiseEvents(Engine engine, IEnumerable<Event> events)
{
EventTransaction transaction = engine.TransactionManager.CreateEventTransaction();
foreach (Event eventInstance in events)
{
transaction.AddEvent(eventInstance);
}
return transaction.CommitTransaction();
}Disposing an EventTransaction also commits it, so you can use a using statement when you do not need the commit result.
You can run multiple event transactions in parallel since each transaction maintains its own context.
Remove event handlers when they are no longer needed:
engine.EventReceived -= OnEventReceived;- About the Report Manager: Running queries against the Directory and processing results.
- About the Engine entity cache: How the Engine caches entity data locally.
- Raising custom events: Defining and raising custom events.
- Receiving actions: Receiving actions directed at entities.
- Event-to-actions: Creating rules that execute actions when events occur.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- ASP.NET hosting
- SDK compatibility
- Migrating to modern .NET
- Entities
- Entity cache
- Entity loading, cache, and query options
- Detecting entity changes
- Entity change event reference
- Transactions
- Security Center events
- Actions
- Security Desk
- Custom events
- Event-to-actions
- Managing macros
- ReportManager
- ReportManager query reference
- Access control raw events
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Entity write restrictions
- About custom fields
- About video
- About cameras
- Enrolling a video unit
- Ingesting third-party video
- Archiver and auxiliary archiver roles
- Archive transfer
- About access control
- About cardholders and credentials
- About doors, areas, elevators, and access points
- About access rules and schedules
- About access control units and interface modules
- Enrolling an access control unit
- Door templates
- Visitors
- Mobile credentials
- About threat levels
- About alarms
- About incidents
- Maps
- Logging
- Overview
- Localization
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Engine extensions
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- Modern .NET support
- Overview
- Localization
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual actions
- Custom 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
- Media file formats
- 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
- Endpoints
- Constants
- Enumerations
- Under the hood
- Troubleshooting