Skip to content

plugin sdk server management

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

About plugin server management

Plugins run as roles that can be assigned to multiple servers for high availability and failover.

Server Assignment Model

Plugin Role
    ↓
Assigned to Server A (Priority 1)
Assigned to Server B (Priority 2)
Assigned to Server C (Priority 3)
    ↓
Runs on highest priority available server
    ↓
Fails over to next server if current fails

Key concepts:

  • Plugins are roles that can run on multiple servers
  • Priority determines which server runs the plugin
  • Automatic failover to next priority server on failure
  • Manual server selection supported
  • Server rejection allows plugins to control where they run

Server Assignment

Adding Servers

Servers are assigned to plugin roles in Config Tool:

Path: System → Roles → [Plugin Role] → Properties → Servers

Administrators can:

  • Add/remove servers
  • Set server priorities
  • Enable/disable automatic failover
  • Manually select running server

Server Priority

Servers have priority levels (1 = highest):

Priority 1: Primary server (preferred)
Priority 2: Secondary server (backup)
Priority 3: Tertiary server (last resort)

Automatic failover behavior:

  • Plugin runs on highest priority available server
  • If that server fails, plugin fails over to next priority
  • When higher priority server recovers, plugin can failover back (if enabled)

High Availability Strategies

Force Execution by Priority

Automatically switches to highest priority server when available:

protected override void OnPluginLoaded()
{
    // Enable automatic priority-based failover
    SetForceExecutionByPriority(true);
}

When enabled:

  • Plugin always runs on highest priority available server
  • Automatically fails back to higher priority servers when they recover
  • Good for active-passive failover scenarios

When disabled:

  • Plugin stays on current server until failure
  • Manual intervention required to switch servers
  • Good for active-active scenarios

Manual Server Selection

Administrator manually controls which server runs the plugin:

// Get current server
Guid currentServer = GetCurrentServer();

// Manually switch to different server
SetCurrentServer(targetServerGuid);

Use cases:

  • Maintenance operations
  • Load balancing
  • Testing
  • Troubleshooting

Server Management Methods

Available through Plugin base class:

GetCurrentServer()

Returns GUID of server currently running the plugin:

protected override void OnPluginLoaded()
{
    Guid serverGuid = GetCurrentServer();
    
    var server = Engine.GetEntity<Server>(serverGuid);
    Logger.TraceInformation($"Plugin running on server: {server.Name}");
    
}

Returns:

  • Server GUID

GetServersInfo()

Returns information about all assigned servers:

protected override void OnPluginLoaded()
{
    Dictionary<Guid, ServerInfos> servers = GetServersInfo();

    foreach (var kvp in servers)
    {
        Guid serverGuid = kvp.Key;
        ServerInfos info = kvp.Value;

        Logger.TraceInformation($"Server: {serverGuid}, Order: {info.Order}");
    }
}

ServerInfos properties:

  • Order - Server priority order (lower numbers = higher priority)
  • NetworkBinding - Network binding configuration for the server

AddServer()

Programmatically add a server to the role:

private void AddBackupServer(Guid serverGuid)
{
    AddServer(serverGuid);
    Logger.TraceInformation($"Added server {serverGuid} to plugin role");
}

Considerations:

  • Server must exist in system
  • Duplicate adds are ignored
  • Priority assigned automatically (lowest available)
  • Config Tool reflects change immediately

RemoveRoleServer()

Remove a server from the role:

private void RemoveServer(Guid serverGuid)
{
    RemoveRoleServer(serverGuid);
    Logger.TraceInformation($"Removed server {serverGuid} from plugin role");
}

Considerations:

  • Cannot remove server if plugin is currently running on it
  • Must switch to different server first
  • Config Tool reflects change immediately

SetCurrentServer()

Manually switch to specific server:

private void FailoverToBackup(Guid backupServerGuid)
{
    Logger.TraceInformation($"Failing over to backup server {backupServerGuid}");
    SetCurrentServer(backupServerGuid);
}

Behavior:

  • Stops plugin on current server
  • Starts plugin on target server
  • May cause brief service interruption
  • Target server must be in role's server list

Important

SetCurrentServer throws if ForceExecutionByPriority is enabled. Disable it first with SetForceExecutionByPriority(false) before manually switching servers.

SetForceExecutionByPriority()

Control automatic priority-based failover:

protected override void OnPluginLoaded()
{
    // Enable automatic failover to highest priority server
    SetForceExecutionByPriority(true);
}

Effect:

  • true - Auto-failover to highest priority available server
  • false - Stay on current server until failure

GetServerCertificate()

Returns the X509 certificate used by the server hosting the plugin:

protected override void OnPluginLoaded()
{
    X509Certificate2 cert = GetServerCertificate();

    if (cert != null)
    {
        Logger.TraceInformation($"Server certificate subject: {cert.Subject}");
        Logger.TraceInformation($"Certificate expires: {cert.NotAfter}");
    }
}

Returns:

  • X509Certificate2 - A clone of the server's certificate
  • null - If no certificate is available

Usage notes:

  • Returns a cloned certificate to prevent disposal of the original
  • Use for validating server identity or establishing secure connections
  • The certificate belongs to the Security Center server hosting the plugin

GetAvailableNetworkCards()

Returns network cards available on each server assigned to the role:

protected override void OnPluginLoaded()
{
    Dictionary<Guid, List<NetworkCard>> networkCards = GetAvailableNetworkCards();

    foreach (var kvp in networkCards)
    {
        Guid serverGuid = kvp.Key;
        List<NetworkCard> cards = kvp.Value;

        var server = Engine.GetEntity<Server>(serverGuid);
        Logger.TraceInformation($"Server {server.Name} has {cards.Count} network cards:");

        foreach (var card in cards)
        {
            Logger.TraceInformation($"  MAC: {card.MacAddress}, IP: {card.IpAddress}");
        }
    }
}

Returns:

  • Dictionary<Guid, List<NetworkCard>> - Server GUID mapped to list of network cards
  • null - If the role entity cannot be found

NetworkCard properties:

  • MacAddress - The MAC address of the network card (or "Any" for default binding)
  • IpAddress - The IPv4 address of the network card

Usage notes:

  • Always includes an "Any" option with empty IP address for default network binding
  • Use to allow administrators to select specific network interfaces
  • Useful for plugins that need to bind to specific network adapters

SetNetworkCard()

Sets the network card binding for a specific server:

private void ConfigureNetworkBinding(Guid serverGuid, NetworkCard selectedCard)
{
    bool success = SetNetworkCard(serverGuid, selectedCard);

    if (success)
    {
        Logger.TraceInformation($"Network card set to {selectedCard.MacAddress}");
    }
    else
    {
        Logger.TraceError("Failed to set network card");
    }
}

Parameters:

  • serverId - The GUID of the server to configure
  • networkCard - The network card to bind to

Returns:

  • true - Network card was set successfully
  • false - Role entity not found

Usage notes:

  • Setting MAC address to "Any" clears the network binding (uses default)
  • Changes are persisted to the role configuration
  • The server must be in the role's server list
  • Use with GetAvailableNetworkCards() to present valid options

Server Rejection

Plugins can reject servers that don't meet requirements:

RejectServer()

Reject current server and trigger failover:

protected override void OnPluginLoaded()
{
    if (!ValidateServerRequirements())
    {
        Guid currentServer = GetCurrentServer();
        RejectServer(currentServer, "Required hardware not available");
        
        Logger.TraceWarning($"Rejected server {currentServer}");
        return; // Don't continue initialization
    }
    
    // Server meets requirements
    AcceptServer(GetCurrentServer());
}

When rejected:

  • Plugin stops on rejected server
  • Security Center attempts to start plugin on next priority server
  • Rejection reason logged and visible in Config Tool
  • Server remains in role's server list but marked as rejected

AcceptServer()

Explicitly accept current server:

protected override void OnPluginLoaded()
{
    if (ValidateServerRequirements())
    {
        AcceptServer(GetCurrentServer());
        Logger.TraceInformation("Server accepted");
    }
}

When to use:

  • After validating server requirements
  • Confirms plugin can run on this server
  • Good practice for explicit acceptance

Server Requirements Validation

Common Validation Scenarios

Hardware requirements:

private bool ValidateServerRequirements()
{
    // Check for required hardware
    if (!IsSerialPortAvailable())
    {
        Logger.TraceError("Serial port not available");
        return false;
    }
    
    // Check for required network access
    if (!CanReachExternalSystem())
    {
        Logger.TraceError("Cannot reach external system");
        return false;
    }
    
    return true;
}

Resource requirements:

private bool ValidateServerRequirements()
{
    // Check available memory
    var availableMemory = GetAvailableMemory();
    if (availableMemory < RequiredMemoryMB)
    {
        Logger.TraceError($"Insufficient memory: {availableMemory}MB < {RequiredMemoryMB}MB");
        return false;
    }
    
    // Check disk space
    var availableDisk = GetAvailableDiskSpace();
    if (availableDisk < RequiredDiskSpaceGB)
    {
        Logger.TraceError($"Insufficient disk space");
        return false;
    }
    
    return true;
}

Software requirements:

private bool ValidateServerRequirements()
{
    // Check for required assemblies
    if (!IsAssemblyAvailable("ThirdParty.Hardware.dll"))
    {
        Logger.TraceError("Required assembly not found");
        return false;
    }
    
    // Check for required services
    if (!IsServiceRunning("RequiredService"))
    {
        Logger.TraceError("Required Windows service not running");
        return false;
    }
    
    return true;
}

Server Lifecycle Events

Plugin Moving Between Servers

Plugin running on Server A
    ↓
Server A fails or priority changes
    ↓
1. Dispose() called on Server A
    ↓
2. Plugin stops on Server A
    ↓
3. Constructor called on Server B
    ↓
4. Initialize() called on Server B
    ↓
5. OnPluginLoaded() called on Server B
    ↓
6. OnPluginStart() called on Server B
    ↓
Plugin running on Server B

Important

  • Complete lifecycle executes on each server
  • No state automatically transferred between servers
  • Must persist state externally (database, file share)
  • Each instance is independent

Persisting State Across Failover

Use database:

public class MyPlugin : Plugin, IPluginDatabaseSupport
{
    protected override void OnPluginStart()
    {
        // Load state from database
        LoadStateFromDatabase();
    }
    
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Save state to database
            SaveStateToDatabase();
        }
    }
}

Use configuration:

protected override void OnPluginLoaded()
{
    // Load state from configuration
    var config = LoadConfiguration();
    RestoreState(config.SavedState);
}

private void OnStateChanged()
{
    // Persist state to configuration
    var config = LoadConfiguration();
    config.SavedState = CaptureState();
    UpdateConfiguration(config);
}

Load Balancing

For plugins that don't require failover (stateless operations):

Active-Active Pattern

protected override void OnPluginLoaded()
{
    // Disable automatic failover
    SetForceExecutionByPriority(false);
    
    // Each instance processes independently
    StartProcessingQueue();
}

Use cases:

  • Stateless query processing
  • Parallel data processing
  • Distributed workloads

Geographic Distribution

protected override void OnPluginLoaded()
{
    Guid currentServer = GetCurrentServer();
    var server = Engine.GetEntity<Server>(currentServer);
    
    // Configure based on server location
    if (server.CustomProperties.Contains("Location:Europe"))
    {
        ConfigureForEuropeRegion();
    }
    else if (server.CustomProperties.Contains("Location:Asia"))
    {
        ConfigureForAsiaRegion();
    }
}

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.
  • 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 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