Skip to content

plugin sdk state management

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

About plugin state management

Plugins report their health and operational status to Config Tool using ModifyPluginState().

State Management Architecture

Plugin detects condition
    ↓
Calls ModifyPluginState()
    ↓
Plugin Host aggregates states
    ↓
Config Tool displays in role diagnostics
    ↓
Role RunningState updated (green/yellow/red)

Key concepts:

  • Multiple state contexts can be active simultaneously
  • States appear in Config Tool diagnostics
  • Error states change role's RunningState to "Not Running" (red)
  • Warning states change role's RunningState to "Warning" (yellow)
  • States persist until cleared or plugin restarts

PluginStateEntry

The PluginStateEntry class represents a single state condition:

public class PluginStateEntry
{
    public PluginStateEntry(string context, string message);

    // Properties (set after construction)
    public string Context { get; set; }
    public string Message { get; set; }
    public string Details { get; set; }
    public Exception Exception { get; set; }
    public bool IsWarning { get; set; }
    public bool IsError { get; set; }
    public DiagnosticLogMessageParsingMode GuidParsingMode { get; set; }
}

Constructor parameters:

  • context - Unique identifier for this state (e.g., "Connection", "Database"). Cannot be null or empty.
  • message - User-friendly description of the state. Set to empty string to clear the context.

Properties (set after construction):

  • IsWarning - Indicates warning state (yellow)
  • IsError - Indicates error state (red). When true, IsWarning is ignored.
  • Exception - Optional exception details
  • Details - Additional detailed message
  • GuidParsingMode - Controls how GUIDs in the message and details are parsed and displayed as clickable entity links in Config Tool diagnostics. Defaults to ParseAnyGuid.

GUID parsing mode

The GuidParsingMode property controls how GUIDs embedded in state messages are detected and converted to clickable entity links in Config Tool's diagnostics view.

public enum DiagnosticLogMessageParsingMode
{
    ParseAnyGuid,           // Default - parses GUIDs with or without brackets
    ParseGuidsWithBrackets, // Only parses GUIDs wrapped in curly brackets
    NoParsing               // No GUID parsing, text displayed as plain text
}

ParseAnyGuid (default):

Detects GUIDs in any format, with or without curly brackets. Both formats become clickable entity links.

// GUID becomes a clickable link to the camera entity
ModifyPluginState(new PluginStateEntry("Status", $"Camera {cameraGuid} is offline"));

ParseGuidsWithBrackets:

Only detects GUIDs explicitly wrapped in curly brackets {...}. Use this when your message contains text that resembles a GUID but is not an entity reference.

// Only the bracketed GUID becomes a clickable link
// "ABC-12345678-DEF" is not parsed as a GUID
var state = new PluginStateEntry("Status",
    $"Camera {{{cameraGuid}}} linked to zone ABC-12345678-DEF")
{
    GuidParsingMode = DiagnosticLogMessageParsingMode.ParseGuidsWithBrackets
};
ModifyPluginState(state);

NoParsing:

Disables all GUID parsing. All text displays as plain text with no clickable links.

// No GUIDs become clickable
var state = new PluginStateEntry("Debug",
    "Transaction ID: 12345678-1234-5678-1234-567812345678")
{
    GuidParsingMode = DiagnosticLogMessageParsingMode.NoParsing
};
ModifyPluginState(state);

When a GUID is parsed, Config Tool resolves it to the entity name and displays it as a clickable link that navigates to that entity.

Reporting Plugin State

Call ModifyPluginState() to report or update the plugin role's state:

protected override void OnPluginLoaded()
{
    try
    {
        InitializeConnection();
        ModifyPluginState(new PluginStateEntry("Connection", "Connected to external system"));
    }
    catch (Exception ex)
    {
        Logger.TraceError(ex, "Connection failed");
        ModifyPluginState(new PluginStateEntry("Connection",
            "Failed to connect to external system")
        {
            Exception = ex,
            IsError = true
        });
    }
}

Reporting Entity State

Use ModifyEntityState() to report state for entities owned by your plugin. This allows individual entities created by your plugin to display their own diagnostics in Config Tool.

protected void ModifyEntityState(Guid entityId, PluginStateEntry state);
protected void ModifyEntityState(Guid entityId, PluginStateEntry state, bool isRunningStateSettable);

Parameters:

  • entityId - The GUID of the entity to attach the state to
  • state - The state entry to report
  • isRunningStateSettable - When true (default), the entity's RunningState is updated based on the state entry. Set to false to report diagnostics without affecting the entity's running state.

Requirements:

  • The entity must be owned by your plugin (entity.OwnerRole == PluginGuid)
  • Or the entity must be the plugin role itself

For more information about plugin entity ownership, see About plugin entity ownership.

Example: Device status reporting

private void UpdateDeviceStatus(Guid deviceEntityId, bool isOnline)
{
    if (isOnline)
    {
        ModifyEntityState(deviceEntityId,
            new PluginStateEntry("Status", "Online"));
    }
    else
    {
        ModifyEntityState(deviceEntityId,
            new PluginStateEntry("Status", "Offline") { IsWarning = true });
    }
}

private void ReportDeviceError(Guid deviceEntityId, Exception ex)
{
    ModifyEntityState(deviceEntityId,
        new PluginStateEntry("Status", "Communication error")
        {
            Exception = ex,
            IsError = true
        });
}

Example: Reporting diagnostics without affecting running state

Use isRunningStateSettable = false when you want to display diagnostic information without changing the entity's running state indicator:

// Report statistics without affecting the entity's green/yellow/red state
ModifyEntityState(deviceEntityId,
    new PluginStateEntry("Statistics", $"Processed {count} events today"),
    isRunningStateSettable: false);

Relationship to ModifyPluginState

ModifyPluginState() is a convenience method that calls ModifyEntityState() with the plugin's own GUID:

// These are equivalent:
ModifyPluginState(new PluginStateEntry("Connection", "Connected"));
ModifyEntityState(PluginGuid, new PluginStateEntry("Connection", "Connected"));

State Types

Success State (Green)

Indicates normal operation:

ModifyPluginState(new PluginStateEntry("Connection", "Connected"));
ModifyPluginState(new PluginStateEntry("Database", "Database operational"));
ModifyPluginState(new PluginStateEntry("Hardware", "All devices online"));

Effect on role:

  • Role shows green (Running) if no error/warning states
  • State appears in diagnostics as informational

Warning State (Yellow)

Indicates degraded operation:

ModifyPluginState(new PluginStateEntry("Connection",
    "Intermittent connection issues") { IsWarning = true });

ModifyPluginState(new PluginStateEntry("Hardware",
    "2 of 10 devices offline") { IsWarning = true });

ModifyPluginState(new PluginStateEntry("Performance",
    "Query response time exceeds threshold") { IsWarning = true });

Effect on role:

  • Role shows yellow (Warning)
  • State appears in diagnostics with warning icon
  • Plugin continues to operate

When to use:

  • Recoverable errors
  • Degraded performance
  • Partial failures
  • Approaching limits

Error State (Red)

Indicates critical failure:

ModifyPluginState(new PluginStateEntry("Connection",
    "Cannot connect to external system") { Exception = ex, IsError = true });

ModifyPluginState(new PluginStateEntry("Database",
    "Database connection lost") { Exception = ex, IsError = true });

ModifyPluginState(new PluginStateEntry("License",
    "License validation failed") { IsError = true });

Effect on role:

  • Role shows red (Not Running)
  • State appears in diagnostics with error icon
  • Plugin may be non-functional

When to use:

  • Connection failures
  • Database errors
  • License/certificate issues
  • Critical resource unavailable

State Contexts

Use different context strings for different subsystems:

// Multiple contexts can be active simultaneously
ModifyPluginState(new PluginStateEntry("Connection", "Connected"));
ModifyPluginState(new PluginStateEntry("Database", "Connected"));
ModifyPluginState(new PluginStateEntry("Hardware", "All devices online"));
ModifyPluginState(new PluginStateEntry("License", "Valid"));

Common context names:

  • "Connection" - External system connectivity
  • "Database" - Database status
  • "Hardware" - Hardware device status
  • "License" - Licensing status
  • "Configuration" - Configuration validation
  • "Performance" - Performance metrics
  • "Startup" - Initialization status

Context best practices:

  • Use descriptive, consistent names
  • One context per subsystem
  • Clear context scope
  • Don't use too many contexts (5-10 max)

Clearing State

Clear a state by setting empty message:

// Report warning
ModifyPluginState(new PluginStateEntry("Connection",
    "Slow response") { IsWarning = true });

// Later, when resolved
ModifyPluginState(new PluginStateEntry("Connection", string.Empty));

When to clear:

  • Condition resolved
  • Subsystem recovered
  • Error no longer applicable

Important

  • Must use same context string to clear
  • Empty message clears the state
  • Cleared states don't appear in diagnostics
  • All states cleared on plugin restart

State Lifecycle

Initialization States

Report progress during initialization:

protected override void OnPluginLoaded()
{
    ModifyPluginState(new PluginStateEntry("Startup", "Initializing..."));
    
    try
    {
        InitializeConnection();
        ModifyPluginState(new PluginStateEntry("Startup", "Connection initialized"));
        
        LoadConfiguration();
        ModifyPluginState(new PluginStateEntry("Startup", "Configuration loaded"));
        
        // Clear startup state when complete
        ModifyPluginState(new PluginStateEntry("Startup", string.Empty));
        
        // Report operational state
        ModifyPluginState(new PluginStateEntry("Status", "Plugin ready"));
    }
    catch (Exception ex)
    {
        ModifyPluginState(new PluginStateEntry("Startup",
            "Initialization failed") { Exception = ex, IsError = true });
    }
}

Runtime State Updates

Update states as conditions change:

private void OnConnectionStateChanged(bool connected)
{
    if (connected)
    {
        ModifyPluginState(new PluginStateEntry("Connection", "Connected"));
    }
    else
    {
        ModifyPluginState(new PluginStateEntry("Connection",
            "Disconnected") { IsWarning = true });

        // Attempt reconnection
        Task.Run(() => AttemptReconnect());
    }
}

private async Task AttemptReconnect()
{
    for (int i = 0; i < 3; i++)
    {
        ModifyPluginState(new PluginStateEntry("Connection",
            $"Reconnecting... (attempt {i + 1}/3)") { IsWarning = true });

        if (await TryConnectAsync())
        {
            ModifyPluginState(new PluginStateEntry("Connection", "Reconnected"));
            return;
        }

        await Task.Delay(TimeSpan.FromSeconds(5));
    }

    ModifyPluginState(new PluginStateEntry("Connection",
        "Reconnection failed") { IsError = true });
}

State Aggregation

The Plugin Host aggregates all plugin states:

Aggregation rules:

  • Any error state → Role shows red (Not Running)
  • Any warning state (no errors) → Role shows yellow (Warning)
  • All success/cleared states → Role shows green (Running)

Example:

// Plugin reports multiple states
ModifyPluginState(new PluginStateEntry("Connection", "Connected")); // Green
ModifyPluginState(new PluginStateEntry("Database", "Connected")); // Green
ModifyPluginState(new PluginStateEntry("Hardware",
    "1 device offline") { IsWarning = true }); // Yellow

// Role overall state: Yellow (Warning) because of hardware warning

Viewing States in Config Tool

Path: System → Roles → [Plugin Role] → Diagnostics

What's displayed:

  • Role's aggregated RunningState (green/yellow/red icon)
  • List of all active states by context
  • State messages
  • Timestamps
  • Exception details (if provided)

States are NOT:

  • Persisted in database
  • Available through SDK queries
  • Visible to end users (Config Tool only)

Common Patterns

Connection Monitoring

private void MonitorConnection()
{
    if (IsConnected())
    {
        ModifyPluginState(new PluginStateEntry("Connection", "Connected"));
    }
    else if (IsConnecting())
    {
        ModifyPluginState(new PluginStateEntry("Connection",
            "Connecting...") { IsWarning = true });
    }
    else
    {
        ModifyPluginState(new PluginStateEntry("Connection",
            "Disconnected") { IsError = true });
    }
}

Configuration Validation

private void ValidateAndApplyConfiguration(PluginConfig config)
{
    if (!ValidateConfiguration(config, out string error))
    {
        ModifyPluginState(new PluginStateEntry("Configuration",
            $"Invalid configuration: {error}") { IsError = true });
        return;
    }

    ModifyPluginState(new PluginStateEntry("Configuration", string.Empty));
    ApplyConfiguration(config);
}

Performance Monitoring

private void MonitorPerformance()
{
    var metrics = GetPerformanceMetrics();

    if (metrics.AverageResponseTime > TimeSpan.FromSeconds(5))
    {
        ModifyPluginState(new PluginStateEntry("Performance",
            $"Slow response time: {metrics.AverageResponseTime.TotalSeconds:F2}s")
            { IsWarning = true });
    }
    else
    {
        ModifyPluginState(new PluginStateEntry("Performance", string.Empty));
    }
}

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.
  • Users and user groups Creating users, managing group membership, and assigning privileges.
  • 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