PeekMessages(Utils.NotifyAsyncServer eventServer, 
            int timeout, System.DateTime messageTimeLimit,
            int totalLimit,
            Func<NotificationMessageHolderType, bool> messageCheck)
        {
            Dictionary<NotificationMessageHolderType, XmlElement> result = new Dictionary<NotificationMessageHolderType, XmlElement>();
            int messagesCount = 0;
            while (true)
            {
                Dictionary<Notify, byte[]> notifications =
                    eventServer.Peek(timeout, _semaphore.StopEvent);

                foreach (Notify notify in notifications.Keys)
                {
                    LogNotificationStep(notifications[notify]);
                    if (notify.NotificationMessage != null)
                    {
                        messagesCount += notify.NotificationMessage.Length;
                    }
                    if (messagesCount>=totalLimit)
                    {
                        break;
                    }
                }
                                
                Dictionary<NotificationMessageHolderType, XmlElement> messages = 
                    GetRawElements(notifications);
                Dictionary<NotificationMessageHolderType, XmlElement> filtered = 
                    GetFilteredList(messages, messageCheck);

                foreach (NotificationMessageHolderType key in filtered.Keys)
                {
                    result.Add(key, filtered[key]);
                }

                if ((messagesCount >= totalLimit) || (messageTimeLimit < System.DateTime.Now))
                {
                    break;
                }
            }
                    
            return result;
        }
        public void AccessDoorTest()
        {
            EndpointReferenceType subscriptionReference = null;
            System.DateTime subscribeStarted = System.DateTime.MaxValue;

            int timeout = _eventSubscriptionTimeout;

            Utils.NotifyAsyncServer eventServer = null;
            RunTest(
                () =>
                {

                    // 3.	Get complete list of doors from the DUT (see Annex A.1).
                    List<DoorInfo> fullDoorsList = GetDoorInfoList();

                    //4.	ONVIF Client selects one door from the complete list of doors at step 
                    // 3 with DoorInfo.Capabilities.Access equal to true. If there is no such Door, 
                    // skip other steps and go to the next test.
                    List<DoorInfo> doorInfos = fullDoorsList.Where(
                        D => D.Capabilities != null &&
                            D.Capabilities.AccessSpecified &&
                            D.Capabilities.Access).ToList();

                    if (doorInfos.Count == 0)
                    {
                        LogTestEvent("No Doors with required Capabilities found, exit the test.");
                        return;
                    }

                    //5.	Test Operator puts Door in state when AccessDoor command will be accepted 
                    // with state change.
                    // ToDo : discuss with customer if there are better methods to select Door 
                    // which will be convenient for operator
                    List<DoorSelectionData.DoorShortInfo> tokens =
                        doorInfos.Select(
                        D => new DoorSelectionData.DoorShortInfo() { Token = D.token, Name = D.Name }).ToList();
                    string selectedToken = tokens.First().Token;

                    string message ="Put the Door with token '{0}' into state which allows 'Access' operation";

                    Definitions.Data.DoorSelectionData data = new TestTool.Tests.Definitions.Data.DoorSelectionData();
                    data.Doors = tokens;
                    data.SelectedToken = selectedToken;
                    data.MessageTemplate = message;

                    WaitHandle formHandle = _operator.ShowCountdownMessage(_messageTimeout, data);
                    try
                    {
                        Sleep(_messageTimeout, new WaitHandle[] { formHandle });
                    }
                    finally
                    {
                        _operator.HideCountdownMessage();
                    }

                    selectedToken = data.SelectedToken;
                    LogTestEvent(string.Format("Door with token '{0}' will be used for test{1}", selectedToken, Environment.NewLine));

                    TopicInfo topic = ConstructTopic(new string[] { "Door", "State", "DoorMode" });
                    TestTool.Proxies.Event.FilterType filter = CreateSubscriptionFilter(topic);

                    Func<NotificationMessageHolderType, bool> messageCheck = (n) => CheckDoorEventSource(n, selectedToken);

                    // Subscribe
                    eventServer = new TestTool.Tests.TestCases.Utils.NotifyAsyncServer(_nic);

                    //SetupNotifyServer2(eventServer);

                    string notificationsUri = eventServer.GetNotificationUri();

                    BeginStep("Begin listening");
                    eventServer.StartCollecting(_semaphore.StopEvent);
                    StepPassed();

                    //6.	ONVIF Client will invoke SubscribeRequest message with tns1:DoorControl/DoorMode 
                    // Topic as Filter and an InitialTerminationTime of 60s to ensure that the SubscriptionManager 
                    // is deleted after one minute.
                    //7.	Verify that the DUT sends a SubscribeResponse message.
                    subscriptionReference = CreateSubscription(filter, timeout, notificationsUri, out subscribeStarted);

                    LogTestEvent(string.Format("Wait until message for Door with token='{0}' is received", selectedToken)+Environment.NewLine);

                    System.DateTime messageTimeLimit = System.DateTime.Now.AddMilliseconds(_operationDelay);

                    string initialMode = string.Empty;
 
                    //8.	Verify that DUT sends Notify message for selected Door with current state 
                    // (Notifications for other Doors will be ignored for this test case).
                    //9.	Verify received Notify message (correct value for UTC time, TopicExpression and 
                    // wsnt:Message).
                    //10.	Verify that PropertyOperation="Initialized".
                    //11.	Verify that TopicExpression is equal to tns1:DoorControl/DoorMode.
                    //12.	Verify that notification contains Source.SimpleItem item with Name="DoorToken" 
                    // and Value is equal to selected Door Token.
                    //13.	Verify that notification contains Data.SimpleItem item with Name="DoorMode" 
                    // and Value with type is equal to tdc:DoorMode.
                    {
                        System.Diagnostics.Debug.WriteLine("Wait for messages with PropertyOperation=INITIALIZED"); 

                        Dictionary<NotificationMessageHolderType, XmlElement> initialMessages =
                            PeekMessages(eventServer, _messageTimeout,
                            messageTimeLimit, fullDoorsList.Count, messageCheck);
                        
                        Assert(initialMessages.Count > 0,
                            string.Format("Message for the door with token='{0}' has not been received", selectedToken ),
                            "Check that the message for selected door has been received");

                        // validate
                        ValidateMessages(initialMessages, topic, OnvifMessage.INITIALIZED, selectedToken, ValidateDoorModeMessage);

                        NotificationMessageHolderType receivedMessage = initialMessages.Keys.First();

                        XmlElement dataElement = receivedMessage.Message.GetMessageData();

                        Dictionary<string, string> dataSimpleItems = dataElement.GetMessageElementSimpleItems();

                        initialMode = dataSimpleItems["State"];
                    }

                    //14.	ONVIF Client will invoke AccessDoorRequest message (Token = [selected Door token]) 
                    // to change door state.
                    //15.	Verify the AccessDoorResponse message from the DUT.
                    AccessDoor(selectedToken, null, null, null, null, null);

                    messageTimeLimit = System.DateTime.Now.AddSeconds(_operationDelay/1000);

                    LogTestEvent("Wait until message with PropertyOperation=\"Changed\" is received" + Environment.NewLine);

                    //16.	Verify that DUT sends Notify message for selected Door with current state 
                    // (Notifications for other Doors will be ignored for this test case).
                    //17.	Verify received Notify message (correct value for UTC time, TopicExpression and 
                    // wsnt:Message).
                    //18.	Verify that PropertyOperation="Changed".
                    //19.	Verify that TopicExpression is equal to tns1:DoorControl/DoorMode.
                    //20.	Verify that notification contains Source.SimpleItem item with Name="DoorToken" 
                    // and Value is equal to selected Door Token.
                    //21.	Verify that notification contains Data.SimpleItem item with Name="DoorMode" 
                    // and Value equal to “Accessed”.
                    {
                        System.Diagnostics.Debug.WriteLine("Wait for first 'CHANGED' message"); 

                        Dictionary<NotificationMessageHolderType, XmlElement> doorModeChangedMessages =
                            PeekMessages(eventServer, _messageTimeout,
                            messageTimeLimit, 1, messageCheck);

                        Assert(doorModeChangedMessages.Count > 0,
                            string.Format("Message for the door with token='{0}' has not been received", selectedToken),
                            "Check that the message for selected door has been received");

                        // validate

                        ValidateMessages(doorModeChangedMessages, topic, selectedToken, ValidateDoorModeMessage);
                    
                        NotificationMessageHolderType receivedMessage = doorModeChangedMessages.Keys.First();
                        ValidateDoorModeSimpleItem(receivedMessage, DoorMode.Accessed);
                    }

                    LogTestEvent("Wait until message with PropertyOperation=\"Changed\" is received" + Environment.NewLine);

                    //22.	ONVIF Client will wait for next Notification for selected Door.
                    //23.	Verify that DUT sends Notify message for selected Door with current state 
                    // (Notifications for other Doors will be ignored for this test case).
                    //24.	Verify received Notify message (correct value for UTC time, TopicExpression 
                    // and wsnt:Message).
                    //25.	Verify that PropertyOperation="Changed".
                    //26.	Verify that TopicExpression is equal to tns1:DoorControl/DoorMode.
                    //27.	Verify that notification contains Source.SimpleItem item with Name="DoorToken" 
                    // and Value is equal to selected Door Token.
                    //28.	Verify that notification contains Data.SimpleItem item with Name="DoorMode" and 
                    // Value equal to previous state (previous state was received with Notification from step 8).
                    {
                        System.Diagnostics.Debug.WriteLine("Wait for second 'CHANGED' message");

                        messageTimeLimit = System.DateTime.Now.AddSeconds(_messageTimeout / 1000);

                        // ToDo: should we wait for "_operationDelay" ?
                        Dictionary<NotificationMessageHolderType, XmlElement> doorModeChangedMessages =
                            PeekMessages(eventServer, _messageTimeout,
                            messageTimeLimit, 1, messageCheck);

                        Assert(doorModeChangedMessages.Count > 0,
                            string.Format("Message for the door with token='{0}' has not been received", selectedToken),
                            "Check that the message for selected door has been received");

                        // validate
                        ValidateMessages(doorModeChangedMessages, topic, selectedToken, ValidateDoorModeMessage);

                        NotificationMessageHolderType receivedMessage = doorModeChangedMessages.Keys.First();
                        ValidateDoorModeSimpleItem(receivedMessage, initialMode);
                    }

                    eventServer.StopCollecting();
                },
                () =>
                {
                    _operator.HideCountdownMessage();
                    if (eventServer != null)
                    {
                        eventServer.StopCollecting();
                    }
                    ReleaseSubscription(subscribeStarted, subscriptionReference, timeout);
                });
        }