-
Notifications
You must be signed in to change notification settings - Fork 6
plugin sdk lifecycle
Understanding the plugin lifecycle is crucial for proper initialization, operation, and cleanup.
flowchart TB
Start[Plugin starts] --> Constructor
subgraph Phase1[" "]
Constructor["1. Constructor called<br/>Engine, Logger, Culture are NULL<br/>PluginGuid is Guid.Empty"]
end
Constructor --> Initialize
subgraph Phase2[" "]
Initialize["2. Initialize(engine, roleGuid, culture) called<br/>Engine, PluginGuid, Logger, Culture populated<br/>Report filters set and handlers registered"]
end
Initialize --> Loaded
subgraph Phase3[" "]
Loaded["3. OnPluginLoaded() called<br/>Called by Initialize()"]
end
Loaded --> Database
subgraph Phase4[" "]
Database["4. Database layer initialized (if IPluginDatabaseSupport)<br/>SetDatabaseInformation and start state machine"]
end
Database --> Started
subgraph Phase5[" "]
Started["5. OnPluginStart() called<br/>Database state may still be connecting"]
end
Started --> Running
subgraph Phase6[" "]
Running["6. Plugin runs<br/>Process queries, handle events/actions<br/>Update entity states"]
end
Running --> Shutdown[7. Plugin shutdown initiated]
Shutdown --> Dispose
subgraph Phase7[" "]
Dispose["8. Dispose() called<br/>Unsubscribe events, stop workers<br/>Dispose resources"]
end
Dispose --> Destroyed[9. Plugin instance destroyed]
| Method | When called | Purpose |
|---|---|---|
Constructor |
Plugin instantiation | Initialize member variables only |
Initialize() |
Called by the plugin host | Set base properties and run OnPluginLoaded()
|
OnPluginLoaded() |
End of Initialize()
|
Register handlers, filters, and services |
OnPluginStart() |
After database layer starts (if supported) | Start background work and runtime processing |
Dispose() |
Plugin shutdown | Clean up resources and unsubscribe events |
The constructor runs early in the lifecycle, so keep the work here minimal and deterministic.
- Engine - null
- Logger - null
- PluginGuid - Guid.Empty
- Culture - null
Initialize member variables only.
public MyPlugin()
{
m_httpClient = new HttpClient();
m_cancellation = new CancellationTokenSource();
}Do not access Engine, Logger, or PluginGuid in the constructor.
Called by the plugin host.
-
Engine,PluginGuid,Logger, andCultureare set. - Report filters are applied from
SupportedQueriesandSupportedCustomReports. - Query and entity event handlers are registered.
-
OnPluginLoaded()is called.
This work is handled by the base Plugin class.
First lifecycle method where you can use the Engine.
- Engine - fully initialized
- Logger - ready to use
- PluginGuid - your role GUID
- Culture - current culture
- Database - may not be ready (if using database support)
protected override void OnPluginLoaded()
{
// Set up event filters
Engine.SetEventFilter(new List<EventType>
{
EventType.AccessGranted,
EventType.DoorOpenedTooLong
});
// Subscribe to events
Engine.EventReceived += OnEventReceived;
Engine.ActionReceived += OnActionReceived;
Engine.EntitiesInvalidated += OnEntitiesInvalidated;
// Register request handlers using Plugin's protected helper methods
AddRequestHandler<MyRequest, MyResponse>(HandleRequest);
// Initialize services (but don't start long-running work yet)
InitializeExternalConnection();
// Report initial state
ModifyPluginState(new PluginStateEntry("Startup", "Plugin loaded"));
}- Do not start background workers yet.
- Do not access the database yet (if using database support).
- Do not perform long-running initialization.
Called after the database layer starts (if supported). The database state can still be connecting.
- Engine - fully initialized
- Database state - may still be connecting (if using database support)
protected override void OnPluginStart()
{
// Start background workers
m_backgroundWorker = Task.Run(() => BackgroundWork(m_cancellation.Token));
// Begin data processing
StartDataProcessing();
// Report ready state
ModifyPluginState(new PluginStateEntry("Running", "Plugin started"));
}- Start background workers
- Begin periodic tasks
- Start data processing
- Perform initialization that does not require a connected database
For database-dependent work, wait for DatabaseState.Connected in OnDatabaseStateChanged().
Called when the plugin is shutting down.
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Unsubscribe from all events
Engine.EventReceived -= OnEventReceived;
Engine.ActionReceived -= OnActionReceived;
Engine.EntitiesInvalidated -= OnEntitiesInvalidated;
// Stop background workers
m_cancellation?.Cancel();
// Remove request handlers
RemoveRequestHandler<MyRequest, MyResponse>(HandleRequest);
// Dispose managed resources
m_httpClient?.Dispose();
m_databaseConnection?.Dispose();
}
}- Unsubscribe from events
- Stop background workers
- Dispose managed resources
- Handle partially initialized state
When a plugin implements IPluginDatabaseSupport, initialization happens in this order:
- Constructor
- Initialize() - base initialization and
OnPluginLoaded()runs - DatabaseManager.SetDatabaseInformation() - connection info provided
- Database layer created - reads
GetDatabaseUpgradeItems() - Database state machine starts
- Creating state calls
GetSpecificCreationScript()when database is missing - Upgrading state runs upgrade items when version is behind
- OnDatabaseStateChanged() notifications for database state changes
- OnPluginStart() is called
- In
OnPluginLoaded(), database may not be ready. -
OnPluginStart()does not guaranteeDatabaseState.Connected. - Use
OnDatabaseStateChanged()to wait forDatabaseState.Connected.
For details, see Plugin SDK database.
Lifecycle methods are called by the plugin host. Callbacks from timers and task continuations run on background threads.
- Use
Engine.QueueUpdate()orEngine.QueueUpdateAndWait()to update entities from background work.
Example: queue an entity update from a timer callback.
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
Engine.QueueUpdate(() =>
{
var entity = Engine.GetEntity<CustomEntity>(m_entityGuid);
entity.RunningState = State.Running;
});
}For detailed threading patterns, QueueUpdate usage, async/await considerations, and background worker examples, see Plugin SDK threading.
- Plugin SDK overview: Plugin architecture, lifecycle, and components.
- Plugin SDK threading: Engine thread, QueueUpdate, and async patterns for plugins.
- Plugin SDK events: Subscribing to events from a plugin role.
- Plugin SDK queries: Implementing custom report queries in a plugin.
-
Plugin SDK database: SQL Server integration through
IPluginDatabaseSupport. - Plugin SDK state management: Reporting plugin and entity health to Config Tool.
- 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