Esempio n. 1
0
        public void CleanUp_ForNotExpiredDeviceInCollection_DoesNotNotifyDeviceExpired(
            ILogger logger,
            IDateTimeOffset dateTimeOffset,
            IDeviceMonitor deviceMonitor,
            ISubject <IDevice> deviceExpired,
            ObservableTimerFactory factory,
            TestScheduler scheduler,
            IDevice device)
        {
            deviceMonitor.DiscoveredDevices
            .Returns(new[] { device });

            var sut = new DeviceMonitorWithExpiry(logger,
                                                  dateTimeOffset,
                                                  deviceMonitor,
                                                  deviceExpired,
                                                  factory,
                                                  scheduler);

            dateTimeOffset.Ticks
            .Returns(sut.TimeOut.Ticks);
            dateTimeOffset.Now
            .Returns(dateTimeOffset);

            device.BroadcastTime
            .Ticks
            .Returns(sut.TimeOut.Ticks / 2);

            scheduler.AdvanceBy(sut.TimeOut.Ticks);

            deviceExpired.DidNotReceive()
            .Publish(device);
        }
Esempio n. 2
0
        public void CleanUp_ForOneExpiredDeviceInCollection_RemovesDeviceFromCollection(
            ILogger logger,
            IDateTimeOffset dateTimeOffset,
            IDeviceMonitor deviceMonitor,
            ISubject <IDevice> deviceExpired,
            ObservableTimerFactory factory,
            TestScheduler scheduler,
            IDevice device)
        {
            deviceMonitor.DiscoveredDevices
            .Returns(new[] { device });

            var sut = new DeviceMonitorWithExpiry(logger,
                                                  dateTimeOffset,
                                                  deviceMonitor,
                                                  deviceExpired,
                                                  factory,
                                                  scheduler);

            dateTimeOffset.Ticks
            .Returns(sut.TimeOut.Ticks);
            dateTimeOffset.Now
            .Returns(dateTimeOffset);

            device.BroadcastTime
            .Ticks
            .Returns(0);

            scheduler.AdvanceBy(sut.TimeOut.Ticks + 1);

            deviceMonitor.Received()
            .RemoveDevice(device);
        }
        public DeviceMonitorWithExpiry(
            [NotNull] ILogger logger,
            [NotNull] IDateTimeOffset dateTimeOffset,
            [NotNull] IDeviceMonitor deviceMonitor,
            [NotNull] ISubject <IDevice> deviceExpired,
            [NotNull] IObservableTimerFactory factory,
            [NotNull] IScheduler scheduler)
        {
            Guard.ArgumentNotNull(logger,
                                  nameof(logger));
            Guard.ArgumentNotNull(dateTimeOffset,
                                  nameof(dateTimeOffset));
            Guard.ArgumentNotNull(deviceMonitor,
                                  nameof(deviceMonitor));
            Guard.ArgumentNotNull(deviceExpired,
                                  nameof(deviceExpired));
            Guard.ArgumentNotNull(factory,
                                  nameof(factory));
            Guard.ArgumentNotNull(scheduler,
                                  nameof(scheduler));

            _logger         = logger;
            _dateTimeOffset = dateTimeOffset;
            _deviceMonitor  = deviceMonitor;
            _deviceExpired  = deviceExpired;

            _timer = factory.Create(TimeOut,
                                    scheduler)
                     .SubscribeOn(scheduler)
                     .Subscribe(CleanUp,
                                OnError,
                                OnCompleted);
        }
Esempio n. 4
0
        public void CleanUp_ForOneExpiredDeviceInCollection_NotifiesDeviceExpired(
            ILogger logger,
            IDateTimeOffset dateTimeOffset,
            IDeviceMonitor deviceMonitor,
            Subject <IDevice> deviceExpired,
            ObservableTimerFactory factory,
            TestScheduler scheduler,
            IDevice device)
        {
            var sut = new DeviceMonitorWithExpiry(logger,
                                                  dateTimeOffset,
                                                  deviceMonitor,
                                                  deviceExpired,
                                                  factory,
                                                  scheduler);

            IDevice expiredDevice = null;

            using var disposable = sut.DeviceExpired
                                   .Subscribe(expired => expiredDevice = expired);

            deviceExpired.OnNext(device);

            scheduler.AdvanceBy(sut.TimeOut.Ticks);

            expiredDevice.Should()
            .Be(device);
        }
        protected override void EstablishContext()
        {
            A.CallTo(() => _contextFactory.Establish(SCardScope.System))
            .Returns(_context);

            A.CallTo(() => _context.IsValid())
            .Returns(true);

            A.CallTo(() => _context.Infinite)
            .Returns(SCardContext.INFINITE);

            // first call -> only one attached reader
            A.CallTo(() => _context.GetReaders())
            .Returns(new[] { READER_A });

            A.CallTo(() => _context.GetStatusChange(SCardContext.INFINITE, A <SCardReaderState[]> .That.Matches(
                                                        states => MatchFirstCall(states))))
            .ReturnsLazily(call => {
                // second call -> two attached readers
                A.CallTo(() => _context.GetReaders())
                .Returns(new[] { READER_A, READER_B });

                _getStatusChangeCall.Set();

                return(SCardError.Success);
            });

            A.CallTo(() => _context.GetStatusChange(SCardContext.INFINITE, A <SCardReaderState[]> .That.Matches(
                                                        states => MatchSecondCall(states))))
            .Returns(SCardError.Cancelled);

            _sut           = new DeviceMonitor(_contextFactory, SCardScope.System);
            _monitorEvents = _sut.MonitorEvents();
        }
 /// <summary>
 /// Releases the smartcard device monitor and its dependencies using the <see cref="IDisposable.Dispose"/> method.
 /// </summary>
 /// <param name="monitor">Smartcard device monitor that shall be stopped and disposed.</param>
 public void Release(IDeviceMonitor monitor)
 {
     if (monitor == null)
     {
         throw new ArgumentNullException(nameof(monitor));
     }
     monitor.Dispose();
 }
Esempio n. 7
0
 public DevicesViewModel(IAdbClient adbClient, IDeviceMonitor deviceMonitor)
 {
     _deviceMontior = deviceMonitor;
     _adbClient     = adbClient;
     UpdateConnectedDevices();
     _deviceMontior.DeviceConnected    += OnDeviceConnected;
     _deviceMontior.DeviceDisconnected += OnDeviceDisconnected;
 }
Esempio n. 8
0
 /// <summary>
 ///
 /// </summary>
 protected void EnableDevicesMonitor()
 {
     deviceMonitor                   = DeviceMonitorFactory.Instance.Create(SCardScope.System);
     deviceMonitor.Initialized      += OnDevicesInitialized;
     deviceMonitor.StatusChanged    += OnDevicesStatusChanged;
     deviceMonitor.MonitorException += OnDevicesMonitorException;
     deviceMonitor.Start();
 }
Esempio n. 9
0
        public void Dispose_ForInvoked_DisposesMonitor(
            DeviceMonitorWithExpiry sut,
            [Freeze] IDeviceMonitor monitor)
        {
            sut.Dispose();

            monitor.Received()
            .Dispose();
        }
Esempio n. 10
0
        public void Stop_ForInvoked_CallsDeviceMonitor(
            DeviceMonitorWithExpiry sut,
            [Freeze] IDeviceMonitor monitor)
        {
            sut.Stop();

            monitor.Received()
            .Stop();
        }
Esempio n. 11
0
        public void RemoveDevice_ForInvoked_CallsDeviceMonitor(
            DeviceMonitorWithExpiry sut,
            [Freeze] IDeviceMonitor monitor,
            IDevice device)
        {
            sut.RemoveDevice(device);

            monitor.Received()
            .RemoveDevice(device);
        }
Esempio n. 12
0
        static void Main(string[] args)
        {
            Console.WriteLine("m = Start monitor");
            Console.WriteLine("e = Start monitor with exception");
            Console.WriteLine("s = Stop current monitor");
            Console.WriteLine("q = Quit program");

            ConsoleKeyInfo key = default(ConsoleKeyInfo);

            while (key.KeyChar != 'q')
            {
                key = Console.ReadKey();

                if (key.KeyChar == 'm')
                {
                    if (monitor == null || currentStatus == MonitorStatus.STOPPED)
                    {
                        Console.WriteLine("Starting monitor with refresh interval of 2 seconds");
                        monitor = new TimerMonitor();
                        monitor.DataReceived += new EventHandler<DataReceivedEventArgs<DateTime>>(monitor_DataReceived);
                        monitor.MonitorStatusChanged += new EventHandler<MonitorStatusEventArgs>(monitor_MonitorStatusChanged);
                        monitor.Start(2000);
                    }

                }
                if (key.KeyChar == 'e')
                {
                    if (monitor == null || currentStatus == MonitorStatus.STOPPED)
                    {
                        Console.WriteLine("Starting monitor with exception occuring on the 20th second");
                        monitor = new TimerMonitorWithException();
                        monitor.MonitorStatusChanged += new EventHandler<MonitorStatusEventArgs>(monitor_MonitorStatusChanged);
                        monitor.DataReceived += new EventHandler<DataReceivedEventArgs<DateTime>>(monitor_DataReceived);
                        monitor.Start(20);
                    }

                }

                if (key.KeyChar == 's')
                {
                    if (monitor != null && currentStatus == MonitorStatus.STARTED)
                    {
                        monitor.Stop();

                    }
                }
            }

            if (monitor != null && currentStatus == MonitorStatus.STARTED)
            {
                monitor.Stop();
                monitor.Dispose();
            }
        }
Esempio n. 13
0
        public void IsListening_ForInvoked_CallsDeviceMonitor(
            DeviceMonitorWithExpiry sut,
            [Freeze] IDeviceMonitor monitor)
        {
            monitor.IsListening
            .Returns(true);

            sut.IsListening
            .Should()
            .BeTrue();
        }
Esempio n. 14
0
        public void DiscoveredDevices_ForInvoked_CallsDeviceMonitor(
            DeviceMonitorWithExpiry sut,
            [Freeze] IDeviceMonitor monitor,
            IReadOnlyCollection <IDevice> collection)
        {
            monitor.DiscoveredDevices
            .Returns(collection);

            sut.DiscoveredDevices
            .Should()
            .BeEquivalentTo(collection);
        }
Esempio n. 15
0
        public void DeviceNameUpdated_ForInvoked_CallsDeviceMonitor(
            DeviceMonitorWithExpiry sut,
            [Freeze] IDeviceMonitor monitor,
            IObservable <IDevice> observable)
        {
            monitor.DeviceNameUpdated
            .Returns(observable);

            sut.DeviceNameUpdated
            .Should()
            .Be(observable);
        }
Esempio n. 16
0
        public void DeviceUpdated(	IDeviceMonitor monitor, IList<DevicePropertyChange> deviceChanges,
            IList<LinePropertyChange> lineChanges, IList<CallPropertyChange> callChanges)
        {
            // FIXME this is very inefficient
            List<PropertyChange> changes = new List<PropertyChange>();
            foreach( PropertyChange change in deviceChanges )
                changes.Add( change );
            foreach( PropertyChange change in lineChanges )
                changes.Add( change );
            foreach( PropertyChange change in callChanges )
                changes.Add( change );

            foreach( PropertyChange change in changes )
                // Note that we log changing to or from any given logging criteria
                if(	LookupPropertyChangeBehaviour( change.Underlying, change.Property, change.ChangedTo ).Log ||
                    LookupPropertyChangeBehaviour( change.Underlying, change.Property, change.ChangedFrom ).Log )
                    Logger.Instance().Log( change.Underlying.GetType().Name + " property " + change.Property + " has changed from " + change.ChangedFrom + " to " + change.ChangedTo );

            // Logging happens here:
            foreach( CallPropertyChange change in callChanges ) {
                if( change.Property == DeviceMonitor.PROPERTY_CALL_ACTIVITY ) {
                    if ( change.ChangedTo == Activity.Connected.ToString() ) {
                        CallRecord call = new CallRecord( monitor.GetDeviceState(), GetLine( change.Call ), change.Call, DateTime.Now, new DateTime() );

                        // Sanity check in case somehow call is already there
                        if ( mCalls.ContainsKey( change.Call ) ) {
                            mCalls.Remove( change.Call );
                            Logger.Instance().Log("Call #" + change.Call.Name + " had to be removed from the call list - did the previous call fail?");
                        }
                        mCalls.Add( change.Call, call );
                    } else if ( change.ChangedFrom == Activity.Connected.ToString() ) {
                        CallRecord call = mCalls[change.Call];
                        call.EndTime = DateTime.Now;
                        CallLogger.Instance().Log(call);
                        mCalls.Remove( change.Call );
                    }
                }

                if (change.Call.Activity != Activity.IdleDisconnected) {
                    if ( mCalls.ContainsKey( change.Call ) ) {
                        CallRecord call = mCalls[change.Call];
                        call.Call = change.Call;
                        call.Line = GetLine(change.Call);
                        mCalls[change.Call] = call;
                    }
                }
            }

            if( StateUpdate != null )
                StateUpdate( monitor, new StateUpdateEventArgs( deviceChanges, lineChanges, callChanges ) );
        }
Esempio n. 17
0
        public void Constructor_ForDateTimeOffsetNull_Throws(
            Lazy <DeviceMonitorWithExpiry> sut,
            [BeNull] IDeviceMonitor deviceMonitor)
        {
            // ReSharper disable once UnusedVariable
            Action action = () =>
            {
                var test = sut.Value;
            };

            action.Should()
            .Throw <ArgumentNullException>()
            .WithParameter(nameof(deviceMonitor));
        }
Esempio n. 18
0
        /// <summary>
        /// Listen to all device events of a given <see cref="IDeviceMonitor"/>.
        /// </summary>
        /// <param name="monitor">The device monitor to listen on.</param>
        /// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
        /// <returns>An observable of reader attached/detached events.</returns>
        public static IObservable <DeviceMonitorEvent> ObserveEvents(this IDeviceMonitor monitor,
                                                                     IScheduler scheduler = null)
        {
            if (monitor == null)
            {
                throw new ArgumentNullException(nameof(monitor));
            }

            var useScheduler = scheduler ?? Scheduler.ForCurrentContext();

            var initialized = Observable.FromEventPattern <DeviceChangeEvent, DeviceChangeEventArgs>(
                handler => monitor.Initialized += handler,
                handler => monitor.Initialized -= handler,
                useScheduler)
                              .Select(ev => ev.EventArgs)
                              .Select(args => new DeviceMonitorInitialized(args));

            var statusChanged = Observable.FromEventPattern <DeviceChangeEvent, DeviceChangeEventArgs>(
                handler => monitor.StatusChanged += handler,
                handler => monitor.StatusChanged -= handler,
                useScheduler)
                                .Select(ev => ev.EventArgs)
                                .SelectMany(CreateEvents);

            var monitorException = Observable
                                   .FromEventPattern <DeviceMonitorExceptionEvent, DeviceMonitorExceptionEventArgs>(
                handler => monitor.MonitorException += handler,
                handler => monitor.MonitorException -= handler,
                useScheduler)
                                   .Select(ev => ev.EventArgs);

            var monitorEvents = initialized
                                .Cast <DeviceMonitorEvent>()
                                .Merge(statusChanged);

            return(Observable.Create <DeviceMonitorEvent>(obs => {
                var subscription = monitorEvents.Subscribe(obs);
                var exceptionSubscription = monitorException
                                            .Take(1)
                                            .Subscribe(args => {
                    subscription.Dispose();
                    obs.OnError(args.Exception);
                });

                return new CompositeDisposable(
                    subscription,
                    exceptionSubscription);
            }));
        }
Esempio n. 19
0
        public Pcsc()
        {
            using (var context = ContextFactory.Instance.Establish(SCardScope.System))
            {
                var readers = context.GetReaders();
                Debug.WriteLine($"NUM READERS: {readers.Count()}");
                foreach (var reader in readers)
                {
                    Debug.WriteLine($"READER: {reader}");
                }

                UpdateReaders(readers.ToList());
            }

            _readersMonitor = DeviceMonitorFactory.Instance.Create(SCardScope.System);
            _readersMonitor.StatusChanged += OnReadersStatusChanged;
            _readersMonitor.Start();
        }
Esempio n. 20
0
        static void Main(string[] args)
        {
            Console.WriteLine("m = Start monitor");
            Console.WriteLine("s = Stop current monitor");
            Console.WriteLine("q = Quit program");

            ConsoleKeyInfo key = default(ConsoleKeyInfo);

            while (key.KeyChar != 'q')
            {
                key = Console.ReadKey();

                if (key.KeyChar == 'm')
                {
                    if (monitor == null || currentStatus == MonitorStatus.STOPPED)
                    {
                        Console.WriteLine("Starting monitor");
                        monitor = new TimerMonitor();
                        monitor.DataReceived += new EventHandler<DataReceivedEventArgs<DateTime>>(monitor_DataReceived);
                        monitor.MonitorStatusChanged += new EventHandler<MonitorStatusEventArgs>(monitor_MonitorStatusChanged);
                        monitor.Start();
                    }

                }

                if (key.KeyChar == 's')
                {
                    if (monitor != null && currentStatus == MonitorStatus.STARTED)
                    {
                        monitor.Stop();

                    }
                }
            }

            if (monitor != null && currentStatus == MonitorStatus.STARTED)
            {
                monitor.Stop();
                monitor.Dispose();
            }
        }
Esempio n. 21
0
        public void OnError_ForInvoked_CallsStop(
            ILogger logger,
            IDateTimeOffset dateTimeOffset,
            IDeviceMonitor deviceMonitor,
            ISubject <IDevice> deviceExpired,
            IObservableTimerFactory factory,
            TestScheduler scheduler)
        {
            factory.Create(Arg.Any <TimeSpan>(),
                           Arg.Any <IScheduler>())
            .Returns(Observable.Throw <long>(new Exception()));

            var sut = new DeviceMonitorWithExpiry(logger,
                                                  dateTimeOffset,
                                                  deviceMonitor,
                                                  deviceExpired,
                                                  factory,
                                                  scheduler);

            scheduler.AdvanceBy(sut.TimeOut.Ticks);

            deviceMonitor.Received()
            .Stop();
        }
Esempio n. 22
0
 protected override void BecauseOf()
 {
     _monitor = _sut.Create(SCardScope.System);
 }
Esempio n. 23
0
 public DeviceMonitorControl( IDeviceMonitor monitor )
 {
     mDeviceMonitor = monitor;
 }
Esempio n. 24
0
        public void StateManagerUpdated( IDeviceMonitor monitor, StateUpdateEventArgs e )
        {
            // Iterate through state changes and deal with them as appropriate:
            List<String> externalProcesses = new List<String>();
            StringBuilder bubbleTextBuilder = new StringBuilder();
            bool showApplication = false;

            // FIXME this is very inefficient
            List<PropertyChange> changes = new List<PropertyChange>();
            foreach( PropertyChange change in e.DeviceStateChanges )
                changes.Add( change );
            foreach( PropertyChange change in e.LineStateChanges )
                changes.Add( change );
            foreach( PropertyChange change in e.CallStateChanges )
                changes.Add( change );

            foreach( PropertyChange change in changes ) {
                PropertyChangeBehaviour behaviour = StateManager.Instance().LookupPropertyChangeBehaviour( change.Underlying, change.Property, change.ChangedTo );

                if( behaviour.ShowBubble ) {
                    if( bubbleTextBuilder.Length > 0 )
                        bubbleTextBuilder.AppendLine();

                    // Substitute in values from pattern.
                    bubbleTextBuilder.Append( FormatString( behaviour.BubbleText, change.Property, change.ChangedFrom, change.ChangedTo ) );
                }

                // Check to see if warning criteria is met.
                if( behaviour.SystemTrayWarning ) {
                    // Activate warning state, if it isn't already:
                    if( ! mWarnings.Contains( change.Underlying.GetHashCode() + ":" + change.Underlying.GetType().Name + ":" + change.Property ) )
                        mWarnings.Add( change.Underlying.GetHashCode() + ":" + change.Underlying.GetType().Name + ":" + change.Property );
                } else {
                    mWarnings.Remove( change.Underlying.GetHashCode() + ":" + change.Underlying.GetType().Name + ":" + change.Property );
                }

                if( behaviour.ShowApplication )
                    showApplication = true;

                if( behaviour.ExternalProcess != "" )
                    externalProcesses.Add( FormatString( behaviour.ExternalProcess, change.Property, change.ChangedFrom, change.ChangedTo ) );
            }

            TreeStates.Invoke(
                new MonitorPassingDelegate( UpdateTree ),
                new Object[] { changes }
            );

            if( showApplication )
                this.Invoke(
                    new ShowFormDelegate( ShowFormMain ),
                    new Object[] {}
                );

            // Enable timer if there are warnings.
            this.Invoke(
                new SetTimer( SetTimerFlash ),
                new Object[] { mWarnings.Count > 0 }
            );

            if( ! TimerFlash.Enabled )
                NotifyIcon.Icon = global::LothianProductions.VoIP.Properties.Resources.HVoIPM_48x;

            foreach( String externalProcess in externalProcesses )
                try {
                    Process.Start( externalProcess );
                } catch( Win32Exception ) {
                    if( bubbleTextBuilder.Length > 0 )
                        bubbleTextBuilder.AppendLine();
                    bubbleTextBuilder.Append( "Failed to launch external process \"" + externalProcess + "\"" );
                }

            if( bubbleTextBuilder.Length > 0 )
                NotifyIcon.ShowBalloonTip(
                    BUBBLE_TIMEOUT,
                    monitor.Name + "'s state changed",
                    bubbleTextBuilder.ToString(),
                    ToolTipIcon.Info
                );
        }
Esempio n. 25
0
        private void AddMonitorToTree( IDeviceMonitor monitor )
        {
            // Use each node's key as a property name. Use each node's tag object as a state.
            Device deviceState = monitor.GetDeviceState();

            TreeNode deviceNode = TreeStates.Nodes.Add( DeviceMonitor.PROPERTY_NAME, deviceState.Name );
            deviceNode.Tag = deviceState;

            for( int i = 0; i < deviceState.Lines.Length; i++ ) {
                TreeNode lineNode = deviceNode.Nodes.Add( DeviceMonitor.PROPERTY_NAME, deviceState.Lines[ i ].Name );
                lineNode.Tag = deviceState.Lines[ i ];

                EnsureNodeContains( lineNode, deviceState.Lines[ i ], DeviceMonitor.PROPERTY_LINE_LASTCALLEDNUMBER, "", deviceState.Lines[ i ].LastCalledNumber );
                EnsureNodeContains( lineNode, deviceState.Lines[ i ], DeviceMonitor.PROPERTY_LINE_LASTCALLERNUMBER, "", deviceState.Lines[ i ].LastCallerNumber );
                EnsureNodeContains( lineNode, deviceState.Lines[ i ], DeviceMonitor.PROPERTY_LINE_MESSAGEWAITING, "", deviceState.Lines[ i ].MessageWaiting.ToString() );
                EnsureNodeContains( lineNode, deviceState.Lines[ i ], DeviceMonitor.PROPERTY_LINE_REGISTRATIONSTATE, "", deviceState.Lines[ i ].RegistrationState.ToString() );

                for( int j = 0; j < deviceState.Lines[ i ].Calls.Length; j++ ) {
                    TreeNode callNode = lineNode.Nodes.Add( DeviceMonitor.PROPERTY_NAME, deviceState.Lines[ i ].Calls[ j ].Name );
                    callNode.Tag = deviceState.Lines[ i ].Calls[ j ];

                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_ACTIVITY, "", deviceState.Lines[ i ].Calls[ j ].Activity.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_BYTESRECEIVED, "", deviceState.Lines[ i ].Calls[ j ].BytesReceived.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_BYTESSENT, "", deviceState.Lines[ i ].Calls[ j ].BytesSent.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_DECODELATENCY, "", deviceState.Lines[ i ].Calls[ j ].DecodeLatency.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_DECODER, "", deviceState.Lines[ i ].Calls[ j ].Decoder );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_DURATION, "", deviceState.Lines[ i ].Calls[ j ].Duration );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_ENCODER, "", deviceState.Lines[ i ].Calls[ j ].Encoder );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_JITTER, "", deviceState.Lines[ i ].Calls[ j ].Jitter.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_PACKETERROR, "", deviceState.Lines[ i ].Calls[ j ].PacketError.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_PACKETLOSS, "", deviceState.Lines[ i ].Calls[ j ].PacketLoss.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_ROUNDTRIPDELAY, "", deviceState.Lines[ i ].Calls[ j ].RoundTripDelay.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_TONE, "", deviceState.Lines[ i ].Calls[ j ].Tone.ToString() );
                    EnsureNodeContains( callNode, deviceState.Lines[ i ].Calls[ j ], DeviceMonitor.PROPERTY_CALL_TYPE, "", deviceState.Lines[ i ].Calls[ j ].Type.ToString() );
                }
            }

            deviceNode.ExpandAll();
        }