Skip to content

AccessSynchronization

Overview

Access control data synchronization between PQ Server and device (credential upload/download, access level sync, offline database management). The adapter implements synchronization logic based on device capabilities.

  • Added in: PQ Framework 2.0
  • Namespace: Pq.Adapters.Framework

When to Use

  • Access control panels with offline credential storage
  • Smart locks with local user databases
  • Door controllers with cached credentials
  • Biometric readers with template storage
  • Any device requiring credential synchronization

States

Synchronization Lifecycle

State Description Status String
Idle No synchronization in progress pq.state.access.sync.idle
Active Synchronization operation in progress pq.state.access.sync.active
Failed Synchronization failed, error condition pq.state.access.sync.failed

Actions

No predefined actions. The adapter implements synchronization logic using:

  • Custom actions for sync events
  • State transitions via base class methods
  • Command handlers for sync requests

Common Adapter-Defined Actions

Adapters typically implement these patterns:

SyncStarted(timestamp) (adapter-defined)

  • Transition to Active state
  • Begin credential upload/download operation

SyncCompleted(timestamp, credentialCount) (adapter-defined)

  • Transition to Idle state
  • Log synchronization success with statistics

SyncFailed(timestamp, errorMessage) (adapter-defined)

  • Transition to Failed state
  • Log synchronization failure with error details

Properties

None. All synchronization configuration is adapter-specific. Define properties in adapter-registration.yaml if needed (e.g., sync_mode, batch_size, retry_policy).

YAML Example

device_types:
  - type_id: AccessControlPanel
    name: "Access Control Panel"
    functions:
      AccessSynchronization:
      ConnectionBase:
    properties:
      sync_mode:
        type: "string"
        default: "auto"
        description: "Synchronization mode: auto, manual, scheduled"
      batch_size:
        type: "int"
        default: 100
        range: [1, 1000]
        description: "Credentials per batch operation"
      offline_capacity:
        type: "int"
        default: 10000
        description: "Maximum offline credentials supported"

  - type_id: SmartLock
    name: "Smart Door Lock"
    functions:
      AccessSynchronization:
      Door:
    properties:
      sync_interval_hours:
        type: "int"
        default: 24
        description: "Hours between automatic synchronization"

Code Usage

public class AccessPanelThing : Thing
{
    public AccessSynchronizationFunction Sync { get; }

    protected override async Task OnSyncRequested(CancellationToken ct)
    {
        // transition to active state
        await Sync.TransitionToAsync("access.sync.active", ct);

        try
        {
            // adapter-specific sync logic
            var credentials = await GetPendingCredentials(ct);
            await UploadToDevice(credentials, ct);

            // transition to idle on success
            await Sync.TransitionToAsync("access.sync.idle", ct);

            Logger.LogInformation("Synchronized {Count} credentials", credentials.Count);
        }
        catch (Exception ex)
        {
            // transition to failed on error
            await Sync.TransitionToAsync("access.sync.failed", ct);

            Logger.LogError(ex, "Synchronization failed");
        }
    }

    private async Task<List<Credential>> GetPendingCredentials(CancellationToken ct)
    {
        // fetch from PQ Server API
        return await ApiClient.GetCredentialsAsync(DeviceId, ct);
    }

    private async Task UploadToDevice(List<Credential> credentials, CancellationToken ct)
    {
        // adapter-specific device communication
        foreach (var batch in credentials.Chunk(BatchSize))
        {
            await DeviceClient.UploadCredentialsAsync(batch, ct);
        }
    }
}

Extended Construction

AccessSynchronization uses extended construction (extended_construction: true). The framework provides:

public class AccessSynchronizationFunction : FunctionBase
{
    // framework provides constructor with Thing reference
    public AccessSynchronizationFunction(Thing thing)
        : base(thing)
    {
    }

    // adapter implements synchronization logic
    public async Task SyncCredentials(List<Credential> credentials, CancellationToken ct)
    {
        await TransitionToAsync("access.sync.active", ct);
        // sync implementation
    }
}

Synchronization Patterns

Full Sync (Initial/Manual)

  1. Device reports firmware version, capacity, current count
  2. Server compares hashes, determines delta
  3. Upload new/changed credentials
  4. Remove deleted credentials
  5. Verify integrity

Incremental Sync (Automatic)

  1. Device polls for changes since last sync
  2. Server returns delta (adds/updates/deletes)
  3. Device applies changes
  4. Device confirms completion

Person Profiles

Access synchronization can include adapter-specific per-person settings declared in access-model.yaml under person_profiles. Use this for panel user flags such as user level, menu type, dual-code mode, or group-selection permission.

When person_profiles is declared, the generated synchronization base calls:

protected override AccessModel.AccessModel Transform(AccessModel.PersonAccess[] persons)

Generated AccessModel.PersonAccess contains typed profile properties, for example person.UserProfile. Adapter code should read those properties directly. The generated mapper applies YAML defaults and validates required profile fields before Transform() runs.

Event-Driven Sync (Real-Time)

  1. Server publishes credential change event
  2. Adapter receives event, filters by device
  3. Adapter pushes change to device immediately
  4. Device acknowledges change

Notes

  • No Predefined Actions: Adapters define custom actions based on device protocol
  • State Tracking: Framework tracks sync state, adapter handles transitions
  • Error Recovery: Adapter implements retry logic, partial sync, rollback
  • Capacity Management: Check device capacity before sync operations
  • Conflict Resolution: Server is authoritative, device reflects server state
  • Performance: Use batch operations, parallel upload when supported

See Also