コード例 #1
0
        private async void _alarmRepository_AlarmChanged(object sender, AlarmChangedEventArgs e)
        {
            // Only handle closed alarms
            if (e.Alarm.StateId != BuiltInAlarmStates.Closed)
            {
                return;
            }

            // If all alarms for this source and event type are closed in VMS, close corresponding alarm in the Demo Access Control system
            var doorId      = e.Alarm.ExternalSourceId;
            var eventTypeId = e.Alarm.ExternalEventTypeId;

            var alarms = _alarmRepository.GetAlarmsForSource(doorId, eventTypeId, false);

            if (!alarms.Any())
            {
                try
                {
                    await _client.CloseAlarmAsync(doorId, eventTypeId);
                }
                catch (DemoApplicationClientException ex)
                {
                    // A retry mechanism would probably be in order...
                    ACUtil.Log(true, "DemoACPlugin.AlarmManager", "Error closing alarm in Demo Access Control system: " + ex.Message);
                }
            }
        }
コード例 #2
0
        public override ACCredentialHolderSearchResults SearchCredentialHolders(string searchString, int searchLimit)
        {
            var partialResult = false;
            var searchResult  = new List <ACCredentialHolderSearchResult>();

            try
            {
                var credentialHolders = _client.SearchCredentialHolders(searchString);

                foreach (var ch in credentialHolders)
                {
                    searchResult.Add(new ACCredentialHolderSearchResult(ch.CredentialHolderId.ToString(), ch.CredentialHolderName, ch.Roles));
                }

                // Demo Access Control system does not support search limit, so we truncate the result
                if (searchResult.Count > searchLimit)
                {
                    searchResult.RemoveRange(searchLimit, searchResult.Count - searchLimit);
                    partialResult = true;
                }
            }
            catch (DemoApplicationClientException ex)
            {
                ACUtil.Log(true, "DemoACPlugin.CredentialHolderManager", "Error searching credential holders: " + ex.Message);
            }
            return(new ACCredentialHolderSearchResults(searchResult, partialResult));
        }
コード例 #3
0
        public sealed override void ApplyConfiguration(ACConfiguration configuration)
        {
            ACUtil.Log(false, "DemoACPlugin.ConfigurationManager", "Configuration applied.");

            // Store the server id - used for connected/disconnected events and when rebuilding the configuration
            _client.ServerId = configuration.ACServer.Id;

            UpdateDoorEnabledState(configuration);
            UpdateEventTypeEnabledState(configuration);

            // Other plug-ins might e.g. need to connect to peers listed in the configuration,
            // or need to look up elements to determine the type or read some custom properties.
        }
コード例 #4
0
        public override void Close()
        {
            _commandManager.Close();
            _configurationManager.Close();
            _connectionManager.Close();
            _credentialHolderManager.Close();
            _eventManager.Close();
            _stateManager.Close();
            _alarmSynchronizer.Close();

            _client.Close();
            ACUtil.Log(false, "DemoACPlugin.DemoAccessControlSystem", "Access control system unloaded.");
        }
コード例 #5
0
 /// <summary>
 /// Validate user credentials for personalized log-in.
 /// </summary>
 public override ACUserCredentialsValidationResult ValidateUserCredentials(string username, string password)
 {
     try
     {
         var valid = _client.CheckCredentials(username, password);
         return(new ACUserCredentialsValidationResult(valid));
     }
     catch (DemoApplicationClientException ex)
     {
         ACUtil.Log(true, "DemoACPlugin.ConnectionManager", "Error validating user credentials: " + ex.Message);
         return(new ACUserCredentialsValidationResult(false));
     }
 }
コード例 #6
0
        private async Task FetchPersonalizedConfigurationAsync(string username, string password, long latestVersion)
        {
            try
            {
                FireFetchPersonalizedConfigurationStatusChanged(new ACFetchPersonalizedConfigurationStatusChangedEventArgs(0, "Waiting for connection to be established", username));

                var authorized = await _client.CheckCredentialsAsync(username, password);

                if (!authorized)
                {
                    FireFetchPersonalizedConfigurationStatusChanged(new ACFetchPersonalizedConfigurationStatusChangedEventArgs("Invalid username or password.", username));
                    return;
                }

                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0.25, "Retrieving door controllers..."));

                var doorControllers = await _client.GetDoorControllersAsync(username, password);

                await Task.Delay(500); // Delay a bit for demonstration

                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0.5, "Retrieving doors..."));

                var doors = await _client.GetDoorsAsync(username, password);

                await Task.Delay(500); // Delay a bit for demonstration

                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0.75, "Retrieving event types..."));

                var eventTypes = await _client.GetEventTypesAsync(username, password);

                await Task.Delay(500); // Delay a bit for demonstration

                var configuration = BuildConfiguration(doorControllers, doors, eventTypes);
                if (configuration != null)
                {
                    // Done
                    FireFetchPersonalizedConfigurationStatusChanged(new ACFetchPersonalizedConfigurationStatusChangedEventArgs(configuration, username, latestVersion.ToString()));
                }
                else
                {
                    FireFetchPersonalizedConfigurationStatusChanged(new ACFetchPersonalizedConfigurationStatusChangedEventArgs("Invalid configuration.", username));
                }
            }
            catch (DemoApplicationClientException ex)
            {
                ACUtil.Log(true, "DemoACPlugin.ConfigurationManager", "Error fetching configuration for user " + username + ": " + ex.Message);
                FireFetchPersonalizedConfigurationStatusChanged(new ACFetchPersonalizedConfigurationStatusChangedEventArgs("Error communicating with the Demo Application.", username));
            }
        }
コード例 #7
0
 public override ACCredentialHolder GetCredentialHolder(string credentialHolderId)
 {
     // This is called when credential holder isn't already cached - look up synchronously
     try
     {
         var credentialHolderDecriptor = _client.GetCredentialHolder(credentialHolderId);
         if (credentialHolderDecriptor != null)
         {
             return(TypeConverter.ToACCredentialHolder(credentialHolderDecriptor, _systemProperties));
         }
     }
     catch (DemoApplicationClientException ex)
     {
         ACUtil.Log(true, "DemoACPlugin.CredentialHolderManager", "Error looking up credential holder: " + ex.Message);
     }
     return(null);
 }
コード例 #8
0
        public override void Init(ACConfiguration configuration)
        {
            ACUtil.Log(false, "DemoACPlugin.DemoAccessControlSystem", "Initializing access control system.");

            _systemProperties = new SystemProperties();
            _client           = new DemoClient(_systemProperties);

            _commandManager          = new CommandManager(_systemProperties, _client);
            _configurationManager    = new ConfigurationManager(_systemProperties, _client, configuration);
            _connectionManager       = new ConnectionManager(_client);
            _credentialHolderManager = new CredentialHolderManager(_systemProperties, _client);
            _eventManager            = new EventManager(_client);
            _stateManager            = new StateManager(_client);

            // Pass the ACAlarmRepository to a separate class for handling two-way alarm synchronization, if needed
            _alarmSynchronizer = new AlarmSynchronizer(_client, ACAlarmRepository);
        }
コード例 #9
0
        private async void _client_CredentialHolderChanged(object sender, CredentialHolderChangedEventArgs e)
        {
            // Fetch the updated credential holder asynchronously before calling FireCredentialHoldersChanged
            try
            {
                var credentialHolderDecriptor = await _client.GetCredentialHolderAsync(e.CredentialHolderId);

                if (credentialHolderDecriptor != null)
                {
                    var credentialHolder = TypeConverter.ToACCredentialHolder(credentialHolderDecriptor, _systemProperties);
                    FireCredentialHoldersChanged(new[] { credentialHolder });
                }
            }
            catch (DemoApplicationClientException ex)
            {
                ACUtil.Log(true, "DemoACPlugin.CredentialHolderManager", "Error updating credential holder: " + ex.Message);
            }
        }
コード例 #10
0
        private async Task RefreshStateAsync(string id, CancellationToken cancellationToken)
        {
            try
            {
                // Only allow one concurrent call to the access control system (VMS will likely request status for all doors on startup)
                await _resolveStateSemaphore.WaitAsync(cancellationToken);

                try
                {
                    // Check if status was already updated
                    var state = GetState(id);

                    if (state == null)
                    {
                        try
                        {
                            var doorStatus = await _client.GetDoorStatusAsync(id);

                            cancellationToken.ThrowIfCancellationRequested();
                            if (doorStatus != null)
                            {
                                state = TypeConverter.ToACState(doorStatus);
                                UpdateState(state);
                                FireStatesChanged(new[] { state });
                            }
                        }
                        catch (DemoApplicationClientException ex)
                        {
                            // Should probably retry on failure
                            ACUtil.Log(true, "DemoACPlugin.StateManager", "Error refreshing state for door " + id + ": " + ex.Message);
                        }
                    }
                }
                finally
                {
                    _resolveStateSemaphore.Release();
                }
            }
            catch (OperationCanceledException)
            { }
        }
コード例 #11
0
 /// <summary>
 /// Execute a command. Used when personalized log-in is enabled.
 /// </summary>
 public override ACCommandResult ExecuteCommand(string operationableInstance, string commandType, string username, string password, string vmsUsername)
 {
     try
     {
         if (commandType == CommandTypes.DoorLock.Id)
         {
             _client.LockDoor(operationableInstance, username, password, vmsUsername);
         }
         else if (commandType == CommandTypes.DoorUnlock.Id)
         {
             _client.UnlockDoor(operationableInstance, username, password, vmsUsername);
         }
         else
         {
             return(new ACCommandResult(false, "Invalid command."));
         }
     }
     catch (DemoApplicationClientException ex)
     {
         ACUtil.Log(true, "DemoACPlugin.CommandManager", "Error executing command " + commandType + " on door " + operationableInstance + ": " + ex.Message);
         return(new ACCommandResult(false, ex.Message));
     }
     return(new ACCommandResult(true));
 }
コード例 #12
0
        private ACConfiguration BuildConfiguration(DoorControllerDescriptor[] doorControllers, DoorDescriptor[] doors, EventDescriptor[] eventDescriptors)
        {
            var elements = new List <ACElement>();

            // Add element types
            elements.Add(ElementTypes.ServerType);
            elements.Add(ElementTypes.DoorControllerType);

            // Add event types
            elements.AddRange(EventTypes.ServerEventTypes);

            foreach (var eventDescriptor in eventDescriptors)
            {
                var acEventType = TypeConverter.ToACEventType(eventDescriptor, !_disabledEventTypes.Contains(eventDescriptor.EventId));
                elements.Add(acEventType);
            }

            // Add state types
            elements.AddRange(StateTypes.ServerStateTypes);
            elements.AddRange(StateTypes.DoorStateTypes);

            // Add command types
            elements.AddRange(CommandTypes.DoorCommands);

            // Look up the all events, which can be fired on a door
            // OBS: In the Demo Access Control application, events with source "DoorController" are actually fired on the door.
            var doorEventTypeIds = eventDescriptors.Where(e => e.SourceType == "Door" || e.SourceType == "DoorController").Select(ed => ed.EventId.ToString());

            elements.Add(ElementTypes.CreateDoorType(doorEventTypeIds));

            // Look up the all events, which can be fired on an access point
            var apEventTypeIds = eventDescriptors.Where(ed => ed.SourceType == "AccessPoint").Select(ed => ed.EventId.ToString());

            elements.Add(ElementTypes.CreateAccessPointType(apEventTypeIds));

            // Add server element
            elements.Add(TypeConverter.CreateACServer(_client.ServerId, _systemProperties.Address));

            // Add door controllers
            foreach (var doorController in doorControllers)
            {
                elements.Add(TypeConverter.ToACUnit(doorController));
            }

            // Add doors and access points
            foreach (var door in doors)
            {
                door.Enabled = !_disabledDoors.Contains(door.DoorId);
                elements.AddRange(TypeConverter.ToACUnits(door));
            }

            try
            {
                return(ACConfiguration.CreateACConfiguration(DateTime.UtcNow, elements));
            }
            catch (ACConfigurationException ex)
            {
                ACUtil.Log(true, "DemoACPlugin.ConfigurationManager", "Error building configuration: " + ex.Message);
                return(null);
            }
        }
コード例 #13
0
        private async Task FetchConfigurationAsync(CancellationToken cancellationToken)
        {
            try
            {
                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0, "Connecting to demo system..."));

                // Check admin credentials (not actually required)
                var valid = await _client.CheckCredentialsAsync(_systemProperties.AdminUser, _systemProperties.AdminPassword);

                await Task.Delay(500, cancellationToken); // Delay a bit for show

                cancellationToken.ThrowIfCancellationRequested();

                if (!valid)
                {
                    FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs("Invalid credentials."));
                    return;
                }

                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0.25, "Retrieving door controllers..."));

                var doorControllers = await _client.GetDoorControllersAsync();

                await Task.Delay(500, cancellationToken); // Delay a bit for demonstration

                cancellationToken.ThrowIfCancellationRequested();

                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0.5, "Retrieving doors..."));

                var doors = await _client.GetDoorsAsync();

                await Task.Delay(500, cancellationToken); // Delay a bit for demonstration

                cancellationToken.ThrowIfCancellationRequested();

                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(0.75, "Retrieving event types..."));

                var eventTypes = await _client.GetEventTypesAsync();

                await Task.Delay(500, cancellationToken); // Delay a bit for demonstration

                cancellationToken.ThrowIfCancellationRequested();

                var configuration = BuildConfiguration(doorControllers, doors, eventTypes);
                if (configuration != null)
                {
                    // Done
                    FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs(configuration));
                }
                else
                {
                    FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs("Invalid configuration."));
                }
            }
            catch (DemoApplicationClientException ex)
            {
                ACUtil.Log(true, "DemoACPlugin.ConfigurationManager", "Error fetching configuration: " + ex.Message);
                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs("Error communicating with the Demo Application."));
            }
            catch (OperationCanceledException)
            {
                FireFetchConfigurationStatusChanged(new ACFetchConfigurationStatusChangedEventArgs("Fetching configuration canceled."));
            }
        }
コード例 #14
0
        private async Task EventPollingAsync(CancellationToken cancellationToken)
        {
            // Demo Access Control system uses sequence numbers based on ticks, so we initialize it to current time
            var seqNr = DateTime.UtcNow.Ticks;

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    // Get events from the Demo Access Control system
                    var events = await TryCall(client => client.GetEventsAsync(_systemProperties.AdminUser, _systemProperties.AdminPassword, 5000, seqNr, _systemProperties.EventPollingCount));

                    if (!_connected)
                    {
                        _connected = true;
                        ACUtil.Log(false, "DemoACPlugin.DemoClient", "Connected to " + _systemProperties.Address);

                        Connected(this, EventArgs.Empty);
                    }

                    if (events.Any())
                    {
                        seqNr = events.Last().SequenceNumber + 1;
                    }

                    foreach (var baseEvent in events)
                    {
                        var dse = baseEvent as DoorStatusEvent;
                        if (dse != null)
                        {
                            var state = TypeConverter.ToACState(dse.Status);
                            StateChanged(this, new StateChangedEventArgs(state));
                            continue;
                        }

                        var dce = baseEvent as DoorControllerEvent;
                        if (dce != null)
                        {
                            var acEvent = TypeConverter.ToACEvent(dce);
                            EventTriggered(this, new EventTriggeredEventArgs(acEvent));
                            continue;
                        }

                        var cce = baseEvent as CredentialHolderChangedEvent;
                        if (cce != null)
                        {
                            CredentialHolderChanged(this, new CredentialHolderChangedEventArgs(cce.CredentialHolderId.ToString()));
                            continue;
                        }

                        var uce = baseEvent as UserChangedEvent;
                        if (uce != null)
                        {
                            UserRightsChanged(this, new UserRightsChangedEventArgs(uce.UserId, uce.UserName, uce.LastChanged));
                            continue;
                        }
                    }

                    // Get alarm to clear from the Demo Access Control system
                    var alarmsToClear = await TryCall(client => client.GetAlarmsToClearAsync(_systemProperties.AdminUser, _systemProperties.AdminPassword));

                    foreach (var clearAlarmCmd in alarmsToClear)
                    {
                        AlarmCleared(this, new AlarmClearedEventArgs(clearAlarmCmd.DoorId.ToString(), clearAlarmCmd.EventTypeId.ToString()));
                    }
                }
                catch (Exception ex)
                {
                    // Connection broken.
                    if (_connected)
                    {
                        _connected = false;
                        ACUtil.Log(true, "DemoACPlugin.DemoClient", "Connection to " + _systemProperties.Address + " failed: " + ex.Message);

                        Disconnected(this, EventArgs.Empty);
                    }
                }

                try
                {
                    await Task.Delay(_systemProperties.EventPollingPeriodMs, cancellationToken);
                }
                catch (OperationCanceledException) { }
            }

            _connected = false;
            ACUtil.Log(false, "DemoACPlugin.DemoClient", "Connection to " + _systemProperties.Address + " closed.");

            // Don't close the client on Disconnect - wait for Close
        }