public async Task Polling()
        {
            var channel = new ClientSessionChannel(
                localDescription,
                certificateStore,
                new AnonymousIdentity(),
                EndpointUrl,
                loggerFactory: loggerFactory);

            await channel.OpenAsync();

            logger.LogInformation($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
            logger.LogInformation($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
            logger.LogInformation($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
            logger.LogInformation($"Activated session '{channel.SessionId}'.");

            var readRequest = new ReadRequest {
                NodesToRead = new[] { new ReadValueId {
                                          NodeId = NodeId.Parse(VariableIds.Server_ServerStatus_CurrentTime), AttributeId = AttributeIds.Value
                                      } }
            };

            for (int i = 0; i < 10; i++)
            {
                var readResult = await channel.ReadAsync(readRequest);

                logger.LogInformation("Read {0}", readResult.Results[0].GetValueOrDefault <DateTime>());
                await Task.Delay(1000);
            }

            logger.LogInformation($"Closing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }
        public async Task Read()
        {
            var channel = new ClientSessionChannel(
                localDescription,
                certificateStore,
                new AnonymousIdentity(),
                EndpointUrl,
                loggerFactory: loggerFactory);

            await channel.OpenAsync();

            logger.LogInformation($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
            logger.LogInformation($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
            logger.LogInformation($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
            logger.LogInformation($"Activated session '{channel.SessionId}'.");

            var readRequest = new ReadRequest {
                NodesToRead = new[] { new ReadValueId {
                                          NodeId = NodeId.Parse(VariableIds.Server_ServerStatus), AttributeId = AttributeIds.Value
                                      } }
            };
            var readResult = await channel.ReadAsync(readRequest);

            var serverStatus = readResult.Results[0].GetValueOrDefault <ServerStatusDataType>();

            logger.LogInformation("Server status:");
            logger.LogInformation("  ProductName: {0}", serverStatus.BuildInfo.ProductName);
            logger.LogInformation("  SoftwareVersion: {0}", serverStatus.BuildInfo.SoftwareVersion);
            logger.LogInformation("  ManufacturerName: {0}", serverStatus.BuildInfo.ManufacturerName);
            logger.LogInformation("  State: {0}", serverStatus.State);
            logger.LogInformation("  CurrentTime: {0}", serverStatus.CurrentTime);

            logger.LogInformation($"Closing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }
        public async Task StructureTest()
        {
            var channel = new ClientSessionChannel(
                localDescription,
                certificateStore,
                new AnonymousIdentity(),
                EndpointUrl,
                loggerFactory: loggerFactory);

            await channel.OpenAsync();

            var readRequest = new ReadRequest
            {
                NodesToRead = new[]
                {
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Structure")
                    },
                },
            };

            var readResponse = await channel.ReadAsync(readRequest);

            foreach (var result in readResponse.Results)
            {
                StatusCode.IsGood(result.StatusCode)
                .Should().BeTrue();
            }

            // reading this node returns an array of ExtensionObjects
            var obj = readResponse.Results[0].Value;

            // create new DataValue for writing.  Most servers reject writing values with timestamps.
            var newValue = new DataValue(obj);

            var writeRequest = new WriteRequest
            {
                NodesToWrite = new[]
                {
                    new WriteValue {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Structure"), Value = newValue
                    },
                },
            };
            var writeResponse = await channel.WriteAsync(writeRequest);

            foreach (var result in writeResponse.Results)
            {
                StatusCode.IsGood(result)
                .Should().BeTrue();
            }

            logger.LogInformation($"Closing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }
        public async Task StackTest()
        {
            var channel = new ClientSessionChannel(
                localDescription,
                certificateStore,
                new AnonymousIdentity(),
                EndpointUrl,
                loggerFactory: loggerFactory);

            await channel.OpenAsync();

            logger.LogInformation($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
            logger.LogInformation($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
            logger.LogInformation($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
            logger.LogInformation($"Activated session '{channel.SessionId}'.");

            var readRequest = new ReadRequest
            {
                NodesToRead = new[]
                {
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Boolean")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.SByte")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int16")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int32")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int64")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Byte")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt16")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt32")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt64")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Float")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Double")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.String")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.DateTime")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Guid")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.ByteString")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.XmlElement")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.LocalizedText")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.QualifiedName")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Boolean")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.SByte")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int16")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int32")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int64")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Byte")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt16")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt32")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt64")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Float")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Double")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.String")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.DateTime")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Guid")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.ByteString")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.XmlElement")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.LocalizedText")
                    },
                    new ReadValueId {
                        AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.QualifiedName")
                    },
                },
            };

            var sw = new Stopwatch();

            sw.Restart();
            for (int i = 0; i < 1; i++)
            {
                var readResponse = await channel.ReadAsync(readRequest);

                foreach (var result in readResponse.Results)
                {
                    StatusCode.IsGood(result.StatusCode)
                    .Should().BeTrue();
                    var obj = result.GetValue();
                }
            }

            sw.Stop();
            logger.LogInformation($"{sw.ElapsedMilliseconds} ms");

            logger.LogInformation($"Closing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }